Mysql Query With JOIN и вложенный не в

0

Итак, у меня есть две таблицы. Одна из них - таблица вопросов, а другая - таблица ответов с приведенной ниже схемой.

Вопрос:

id title category_id active

Ответ:

id question_id player_id active

В принципе, мне нужен запрос, чтобы получить количество вопросов, оставшихся сгруппированными для каждого игрока для определенной category_id

SELECT * FROM questions WHERE id NOT IN (SELECT DISTINCT(s.question_id) FROM answers s) 

Он возвращает мне оставшиеся вопросы, но он не сгруппирован для конкретного игрока, и если он соединен с одной и той же таблицей ответов, то набор результатов пуст.

Запрос, который я пробовал:

SELECT g.player_id, COUNT(questions.question_id) as Count
FROM    'questions' JOIN answers g ON g.id = questions.id
WHERE g.question_id NOT IN
    (
    SELECT  DISTINCT(question_id)
    FROM  answers
    ) GROUP BY g.player_id

Я уже получил желаемый результат с помощью PHP и использовал несколько циклов для получения требуемого набора, и это не оптимизированное решение и занимает много времени. Итак, вы хотите решить это, написав правильный запрос.

Спасибо за ваше время и оцените, если кто-нибудь может вести меня.

Данные таблицы:

Вопросы:

id title category_id active
 1   A     1          1
 2   B     1          1
 3   C     1          1
 4   D     1          1
 5   E     1          1

ответы:

id question_id player_id active
 1    1           1       1
 1    3           1       1
 1    2           2       1
 1    4           3       1

Ожидаемый результат:

 player_id Count_of_Remaining_Questions Category ID
   1            3                           1
   2            4                           1
   3            4                           1
  • 0
    Обратите внимание, что DISTINCT не является функцией.
  • 0
    @ Клубника О! Забыл это. Благодарю. Буду иметь в виду. В ожидании запроса.
Показать ещё 7 комментариев
Теги:

3 ответа

2
Лучший ответ

Предположим, что таблица players с этой упрощенной схемой:

id | name

Теперь вы можете присоединиться к этой таблице со своей таблицей вопросов:

SELECT 
  p.id AS player_id,
  q.id AS question_id
FROM
  players p
CROSS JOIN
  questions q

Это приведет к списку всех возможных комбинаций игроков и вопросов. Теперь вы можете присоединиться к этим ответам с помощью LEFT JOIN и отфильтровать ответы:

SELECT 
  p.id AS player_id,
  q.id AS question_id
FROM
  players p
CROSS JOIN
  questions q
LEFT JOIN
  answers a 
    ON a.question_id = q.id 
    AND a.player_id = p.id
WHERE
  a.id IS NULL

Это уменьшит прежний список до всех оставшихся без ответа вопросов. Теперь просто заполните группу игроком и категорией, чтобы получить окончательный список:

SELECT 
  p.id AS Player,
  COUNT(q.id) AS Remaining,
  q.category_id AS Category
FROM
  players p
CROSS JOIN
  questions q
LEFT JOIN
  answers a 
    ON a.question_id = q.id 
    AND a.player_id = p.id
WHERE
  a.id IS NULL
GROUP BY
  p.id,
  q.category_id

Обновление. Чтобы получить список игроков, которые уже ответили на все вопросы, нам нужно изменить логику. Вместо того, чтобы проверять ответы на оставшиеся без ответа вопросы (WHERE a.id IS NULL), мы теперь сравним сумму идентификаторов вопросов в обоих табличных questions (чтобы получить ссылку на все вопросы) и answers (чтобы рассчитать баллы для каждого игрока/категории). Только если оба значения равны (HAVING SUM(a.question_id) = SUM(q.id)), индивидуальный игрок ответил на все вопросы (при условии, что на игрока есть только одна строка ответа и вопрос.

SELECT 
  p.id AS Player,
  COUNT(q.id) AS Remaining,
  q.category_id AS Category
FROM
  players p
CROSS JOIN
  questions q
LEFT JOIN
  answers a 
    ON a.question_id = q.id 
    AND a.player_id = p.id
GROUP BY
  p.id,
  q.category_id
HAVING
  SUM(a.question_id) = SUM(q.id)
  • 0
    Спасибо за вашу помощь. Отлично работает. Я сделал несколько небольших изменений. Тем не менее, у меня есть еще одна вещь, чтобы спросить. Он не возвращает player_id для какой-либо конкретной категории, когда у них осталось 0 вопросов. Можем ли мы получить счет только тех игроков, у которых осталось 0 вопросов?
  • 0
    Ну, это еще одна задача. Добавляя WHERE a.id IS NULL мы специально перечисляем игроков, у которых остался хотя бы один вопрос. Не могли бы вы указать требования? То есть теперь вам нужен список игроков, которые ответили на все вопросы?
Показать ещё 3 комментария
1

Вы можете перейти к answers и таблицам questions а затем снова присоединиться к таблице answers чтобы найти недостающие ответы:

select     a.player_id, 
           count(distinct q.id) as count
from       answers a
cross join questions q
left join  answers a2
        on a2.question_id = q.id
       and a2.player_id = a.player_id
where      a2.question_id is null
and        q.category_id = 1
and        q.active = 1
group by   a.player_id
1

Вы можете использовать кросс-соединение, чтобы получить все возможные вопросы для каждого пользователя, а затем не в каждом из пользователей, которые могли бы получить значение для вашей статистики

   select player_id, count(*), category_id
   from (

      select a2.player_id, q.id, q.category_id 
      from answer  a2
      cross join question q 
      where (a2.player_id, q.question_id ) not in (
         select a.question_id, a.player_id
         from Answers a ) 
    ) t
    group by player_id, category_id
  • 0
    @ trincot спасибо .. проверил ..

Ещё вопросы

Сообщество Overcoder
Наверх
Меню