SQL: правильный способ получить первый ряд группы - PullRequest
0 голосов
/ 16 ноября 2018

Я перевожу сайт в службу Google Cloud SQL, которая имеет странное значение по умолчанию с ONLY_FULL_GROUP_BY, что означает, что общий шаблон, который я использую, внезапно выходит из строя.

Примите во внимание следующее:

SELECT `p`.`id`, `p`.`name`, `s`.`name` AS `latest_purchase`, `s`.`price` AS `latest_purchase_price`
FROM `Person` p
JOIN `Sales` s ON `s`.`person` = `p`.`ID`
GROUP BY `p`.`id`
ORDER BY `p`.`time` DESC

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

Поведение частичной группировки Яиспользуется в MySQL отлично подходит для этого, потому что он группирует только по идентификатору человека, и так как мои результаты упорядочены, первая строка каждой группы - это та, которую я хочу, поэтому я получаю ожидаемые результаты.

Но это не разрешено в режиме SQL ONLY_FULL_GROUP_BY, который требует, чтобы все выбранные элементы были либо в предложении GROUP BY, либо использовали агрегатные функции для выбора одного результата.

Ни одна из этих работв приведенном выше примере, потому что добавление всего к GROUP BY означает, что я получу несколько результатов на человека, в то время как использование агрегатных функций может дать неточный результатпоскольку цена продажи не обязательно является самой высокой или самой низкой в ​​группе (я мог бы в итоге получить название и цену продажи, ни одна из которых не является последней).

К счастью, режим SQL является одним изНастройки Google SQL позволяют пользователю изменять, поэтому я только что сделал это (отредактируйте экземпляр и перейдите к установке флагов).

Однако, если бы я использовал другую систему в будущем, где я смогуне группируйте, как мне хочется, тогда каков «правильный» способ сделать это, если частичная группировка не разрешена?

Я понимаю, что уже есть некоторые похожие вопросы по StackOverflow, но ни одного из них я не нашелвполне отражает мою проблему (поскольку они включают гораздо более простые примеры, в которых могут использоваться агрегатные функции).

1 Ответ

0 голосов
/ 16 ноября 2018

То, что вы хотите, это фильтрация не агрегация :

SELECT `p`.`id`, `p`.`name`, `s`.`name` AS `latest_purchase`, `s`.`price` AS `latest_purchase_price`
FROM `Person` p JOIN
     `Sales` s
     ON `s`.`person` = `p`.`ID`
WHERE s.time = (SELECT MAX(s2.time) FROM sales s2 WHERE s2.person = s.person)
ORDER BY `p`.`time` DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...