SQL запрос для группировки и агрегирования результатов - PullRequest
0 голосов
/ 05 мая 2020

Учитывая этот образец данных:

select 'Ada' name, 'Apple' fruit, 2 score union all
select 'Ada', 'Apple', 10 union all
select 'Ada', 'Banana', 8 union all
select 'Ada', 'Cherry', 8 union all
select 'Bob', 'Apple', 5

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

name | fruit         | score
-----+---------------+------
 Ada | Apple         | 10
 Ada | Banana,Cherry | 8
 Bob | Apple         | 5

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

Я могу добиться этого с помощью

select name, string_agg(fruit, ','), score from (
    select name, fruit, max(score) score from (
        select 'Ada' name, 'Apple' fruit, 2 score union all
        select 'Ada', 'Apple', 10 union all
        select 'Ada', 'Banana', 8 union all
        select 'Ada', 'Cherry', 8 union all
        select 'Bob', 'Apple', 5
    ) data
    group by name, fruit
) data
group by name, score

Есть ли более простой способ написать запрос одним единственным выбором вместо этого из двух?

«Нет» - приемлемый ответ, если вы можете объяснить, почему написать его с одним выбором невозможно.

1 Ответ

2 голосов
/ 05 мая 2020

Насколько я знаю, это невозможно сделать за один шаг, потому что вам нужно использовать две разные группы: одну для получения максимального количества очков за имя и фрукт, а другую для string_agg, т.е. на основе агрегирования из первого запроса.

При этом его можно записать немного более читаемым способом, используя общее табличное выражение:

WITH cte AS
(
    SELECT name, fruit, max(score) As score 
    FROM (
        SELECT 'Ada' name, 'Apple' fruit, 2 score UNION ALL
        SELECT 'Ada' name, 'Apple' fruit, 2 score UNION ALL
        SELECT 'Ada', 'Apple', 10 UNION ALL
        SELECT 'Ada', 'Banana', 8 UNION ALL
        SELECT 'Ada', 'Cherry', 8 UNION ALL
        SELECT 'Bob', 'Apple', 5
    ) data
    GROUP BY name, fruit
)

SELECT name, STRING_AGG(fruit, ','), score 
FROM cte
GROUP BY name, score
...