ВЫБЕРИТЕ МИНИМАЛЬНОЕ значение с помощью GROUP BY и INNER JOIN?

#mysql

Вопрос:

У меня есть запрос, извлекающий данные из 4 разных таблиц;

 SELECT cd.name, tt.card_number, tt.deck_count, tcg.url, MIN(tcgp.marketPrice) as 'price'
FROM card_occurrences tt
INNER JOIN card_database cd ON tt.card_number = cd.id
INNER JOIN tcgplayer_cards tcg ON cd.name = tcg.name
INNER JOIN tcgplayer_set_prices tcgp ON tcgp.productId = tcg.productID
GROUP BY tt.card_number
ORDER BY tt.deck_count DESC LIMIT 100
 

Однако tcg.url это неправильно, и я знаю, что это результат использования MIN(tcgp.marketPrice) with GROUP BY .

Если я исключу MIN and `GROUP BY, я получу негруппированные результаты следующим образом: введите описание изображения здесь

Однако, когда я делаю MIN с GROUP BY then, я правильно получаю самую низкую цену, но URL неверен. Он получает первое найденное. введите описание изображения здесь

Я думаю, мне нужно использовать другой оператор JOIN (или, может быть, подзапрос?) но я не совсем уверен. Приветствуется некоторое подталкивание в правильном направлении!

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

1. Прежде всего, именно по этой причине вы никогда не должны отключать ONLY_FULL_GROUP_BY в своей конфигурации mysql. В основном вы получите нежелательные результаты, если вы группируете только по одному столбцу и выбираете другие. Чтобы получить желаемый результат, я бы использовал дополнительный выбор, сначала выбирая все минимальные значения, а затем добавляя другие столбцы.

2. Если вы предполагаете, что MIN() функция вернет соответствующее значение во всех других столбцах, это неверно. Если вы используете версию MySQL, которая поддерживает функцию window (v8 ), то вы можете попробовать использовать ROW_NUMBER() функцию с желаемой сортировкой (по номеру строки), а затем отфильтровать ее оттуда.

Ответ №1:

Если вы используете MySQL v8 (или MariaDB 10.2 ), то я думаю, вам следует попробовать использовать ROW_NUMBER() . Рассмотрим этот пример:

 SELECT cd.name, tt.card_number, tt.deck_count, tcg.url, tcgp.marketPrice as 'price',
       ROW_NUMBER() OVER (PARTITION BY cd.name, tt.card_number ORDER BY tcgp.marketPrice) rn
FROM card_occurrences tt
INNER JOIN card_database cd ON tt.card_number = cd.id
INNER JOIN tcgplayer_cards tcg ON cd.name = tcg.name
INNER JOIN tcgplayer_set_prices tcgp ON tcgp.productId = tcg.productID;
 

ROW_NUMBER() OVER (PARTITION BY cd.name, tt.card_number ORDER BY tcgp.marketPrice) rn Функция присваивает номер строки значению строки на основе tcgp.marketPrice возрастания, сохраняя при этом соответствующее значение столбца для строки.

Демонстрационная скрипка