Задать вопрос
Dier_Sergio_Great
@Dier_Sergio_Great
Увлеченный человек

Как вывести по 5 максимальных значений в строках из каждой категории?

Отчёт для формы для голосования кино.
Нужно вывести по каждой номинации 5 фильмов с максимальным количеством балов.
Каждая строка таблицы это 1 голос: колонки nomin_id, user_id, film_id
SELECT count(user_id ) countUser , nomin_id,  film_id 
FROM votes
GROUP BY  film_id , nomin_id
ORDER BY countUser DESC
LIMIT 5;

По идее надо этот запрос таблицы votes вложить в другой запрос таблицы votes и проверять есть ли совпадения двух таблиц WHERE EXISTS().
Но всего в таблице 25 000 строк запрос выполняется 30 секунд, а потом крах.
  • Вопрос задан
  • 730 просмотров
Подписаться 4 Простой 1 комментарий
Решения вопроса 2
@alexalexes
select A.*
       from
       (
       select B.*,
              row_number() over (partition by B.nomin_id order by B.countUser desc) rwnm -- партишином задаем область счета строк, а сортировкой - порядок счета
              from
              (
              SELECT count(user_id) countUser, nomin_id,  film_id
              FROM votes
              GROUP BY  film_id , nomin_id
              ) B
       ) A
where rwnm <= 5 -- берем по этому количеству от каждого локального счета

См. оконную функцию row_number для MySQL 8+ версия, либо MariaDB. Но учтите, что MySQL 5 не поддерживает оконки, в ней свои костыли есть в виде использования переменных с @.

Но всего в таблице 25 000 строк запрос выполняется 30 секунд, а потом крах.

Индексы на каждый из атрибутов user_id, nomin_id, film_id нужно создать, тогда будет пару сотен миллисекунд выполняться.
Ответ написан
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
То же самое, что у alexalexes, только в более линейном виде.
WITH
  `counts` AS (
    SELECT `film_id`, `nomin_id`, COUNT(*) AS `votes_count`, 
      FROM `votes`
      GROUP BY `nomin_id`, `film_id`
  ).
  `places` AS (
    SELECT `film_id`, `nomin_id`, `votes_count`,
           ROW_NUMBER() OVER `win` AS `place`
      FROM `counts`
      WINDOW `win` AS (
        PARTITION BY `nomin_id`
        ORDER BY `votes_count` DESC
      )
  )
SELECT `votes_count`, `nomin_id`, `film_id`, `place`
  FROM `places`
  WHERE `place` <= 5
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы