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

#mysql #multiple-choice

#mysql #множественный выбор

Вопрос:

У меня есть приложение с множественным выбором элементов, опций, ответов и пользовательских таблиц:

  • Элемент — это, по сути, вопрос. Каждый элемент относится к одной из трех категорий. Категория хранится в виде строки в category поле.
  • С каждым элементом связано несколько параметров. У каждого параметра есть item_id и points поля.
  • Всякий раз, когда пользователь выбирает вариант, создается ответ. В нем есть user_id , item_ id и option_id поля. На пару элемент / пользователь дается ровно один ответ.

Что мне нужно

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

 Name | Points in Cat1 | Points in Cat2 | Points in Cat3
John | 3              | 1.5            | 2 
Jane | 2              | 2              | 1.5
  

Что у меня есть

Я могу выводить точки, сгруппированные по пользователю и категории в отдельных строках:

 SELECT
  u.id,
  u.first_name,
  i.category,
  sum(o.points)

FROM 
  answers a,
  options o,
  items i,
  users u

WHERE a.user_id = u.id
  AND a.option_id = o.id
  AND o.item_id = a.item_id
  AND i.id = a.item_id

GROUP BY u.id, i.category;

# Output:
# John   Cat1   3
# John   Cat2   1.5
# John   Cat3   2
# Jane   Cat1   2
# etc.
  

Мне нужна помощь в изменении запроса во втором списке кода таким образом, чтобы получить те же данные, но в формате, который я набросал в первом списке.

Комментарии:

1. Вместо ответа, приведенного ниже, серьезно рассмотрите проблемы отображения данных в коде приложения.

2. Спасибо! На самом деле это именно то, что я собираюсь сделать, когда проведу рефакторинг приложения и интегрирую его с другим. Просто в atm вообще нет серверной части, и я не хочу тратить много времени на эту версию.

Ответ №1:

используйте условную агрегацию с регистром, когда выражение

 select firstname,
       max(case when category='Cat1' then p end) "Points in Cat1"
       max(case when category='Cat2' then p end) "Points in Cat2",
       max(case when category='Cat3' then p end) "Points in Cat3"
from
(
SELECT
  u.id,
  u.first_name,
  i.category,
  sum(o.points) as p
FROM 
  answers a join users u on a.user_id = u.id join options o on a.option_id = o.id
  join items i on i.id = a.item_id
GROUP BY u.id, i.category, u.id,u.first_name
)AA group by firstname
  

Комментарии:

1. Спасибо, это как раз то, что мне было нужно. Однако есть опечатка: «firstname» должно быть «first_name», и я использовал «group by id» вместо «group by firstname», потому что имена могут быть не уникальными.