SQL: результат запроса foreach - выполнить запрос - PullRequest
2 голосов
/ 19 февраля 2020

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

Я думаю, мне нужно сделать что-то вроде

SELECT DISTINCT category_id from tableX;

Затем выполнить foreach для получения этих результатов с помощью другой запрос типа

SELECT * from tableX where category_id = ${1} ORDER BY rating, LIMIT 1;

ИЛИ что-то вроде

call foreach('SELECT distinct category_id FROM tableX', 'SELECT * from tableX WHERE category_id = ${1} ORDER BY rating DESC LIMIT 1')

Редактировать:

Я добавил несколько строк примеров

CREATE TABLE `tableX` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `rating` double(6,1) DEFAULT '0.0',
  `category_id` int(10) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Сброс данных для таблицы tableX

INSERT INTO `tableX` (`id`, `rating`, `category_id`) VALUES
(1463, 8.0, 1),
(1464, 8.0, 1),
(1465, 8.0, 1),
(1466, 9.0, 1),
(1467, 9.0, 1),
(1468, 3.0, 1),
(1469, 8.0, 1),
(1470, 2.0, 1),
(1471, 4.0, 1),
(1472, 9.0, 1),
(1473, 5.0, 1),
(1474, 9.0, 1),
(1475, 10.0, 1),
(1476, 7.0, 1),
(1477, 7.0, 1),
(1478, 6.0, 1),
(1479, 10.0, 1),
(1480, 3.0, 1),
(1481, 7.0, 1),
(1482, 4.0, 1),
(1483, 7.0, 1),
(1484, 4.0, 1),
(1485, 2.0, 1),
(1486, 4.0, 1),
(1487, 5.0, 1),
(1488, 9.0, 1),
(1489, 8.0, 1),
(1490, 7.0, 1),
(1491, 10.0, 1),
(1492, 9.0, 1),
(1493, 9.0, 1),
(1494, 9.0, 2),
(1495, 3.0, 2),
(1496, 9.0, 2),
(1497, 9.0, 2),
(1498, 2.0, 2),
(1499, 4.0, 2),
(1500, 5.0, 2),
(1501, 7.0, 2),
(1502, 5.0, 2),
(1503, 7.0, 2),
(1504, 10.0, 2),
(1505, 6.0, 2),
(1506, 6.0, 4),
(1507, 1.0, 4),
(1508, 5.0, 4),
(1509, 7.0, 5),
(1510, 4.0, 5);

Индексы для дампированных таблиц

ALTER TABLE `tableX`
  ADD PRIMARY KEY (`id`),
  ADD KEY `category_id` (`category_id`);

1 Ответ

0 голосов
/ 19 февраля 2020

Используйте rank() или row_number():

select x.*
from (select x.*,
             row_number() over (partition by category_id order by rating desc) as seqnum
      from tableX x
     ) x
where seqnum = 1;

Для связей используйте rank() (то есть все строки с наивысшим рейтингом).

То, что выше работает в MySQL 8+. В более ранних версиях вы можете использовать коррелированный подзапрос. Что-то вроде:

select x.*
from tableX x
where x.rating = (select max(x2.rating)
                  from tableX x2
                  where x2.category_id = x.category_id
                 );

Если вы хотите использовать только одну строку, используя вторую форму, то:

select x.*
from tableX x
where x.id = (select x2.id
              from tableX x2
              where x2.category_id = x.category_id
              order by x2.rating desc
              limit 1
             );
...