Использование GROUP BY в SQL с МАКСИМАЛЬНЫМ агрегатом и выбор дополнительного столбца, которого нет в инструкции GROUP BY

#sql #postgresql

#sql #postgresql

Вопрос:

 SELECT sq.type, sq.cust, MAX(sq.sum)
FROM (
    SELECT C.custid AS cust, P.ptype AS type, SUM(D.qty) AS sum
    FROM Customers C, Orders O, Details D, Products P
    WHERE C.custid = O.ocust and D.ordid = O.ordid and P.pcode = D.pcode    
    GROUP BY cust, type
) as sq
GROUP BY sq.type
;
  

Привет, друзья,

Моя проблема в том, что я хочу иметь возможность выбирать sq.cust, а также sq.type с помощью функции group by в SQL. При использовании MAX aggregate он в любом случае должен возвращать только 1 кортеж, который включает sq.type и sq.cust, так почему же я не могу получить к нему доступ таким образом? Есть ли какой-либо способ вернуть идентификатор клиента (sq.cust) максимальной суммы sq. для этого типа продукта (sq.type)?

Спасибо!

Ответ №1:

Никогда не используйте запятые в FROM предложении. Всегда используйте правильный, явный, стандартный JOIN синтаксис.

Тем не менее, вы можете использовать distinct on в Postgres:

 SELECT DISTINCT ON (ptype) C.custid as cust, P.ptype AS type, SUM(D.qty) AS sum
FROM Customers C JOIN
     Orders O
     ON C.custid = O.ocust JOIN
     Details D
     ON D.ordid = O.ordid JOIN
     Products P
     ON P.pcode = D.pcode    
GROUP BY cust, ptype
ORDER BY ptype, SUM(d.QTY) DESC
  

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

1. Есть ли способ сделать это без distinct on?

2. @Keeyan . . . Да, но distinct on обычно это самый эффективный метод в Postgres.

Ответ №2:

Решение от Гордона Линоффа отличное, хотя и специфичное для Pg. Чтобы сделать его немного более переносимым, можно использовать оконные функции, которые сейчас доступны в большинстве основных СУБД.

Например, в SQL Server:

 select C.custid as cust, P.ptype, sum(qty) as sum_qty
    , FIRST_VALUE(sum(qty)) OVER (PARTITION BY ptype ORDER BY SUM(qty) DESC) as max_sum_qty_for_ptype
FROM Customers C JOIN
     Orders O
     ON C.custid = O.ocust JOIN
     Details D
     ON D.ordid = O.ordid JOIN
     Products P
     ON P.pcode = D.pcode

GROUP BY cust, ptype
ORDER BY ptype, SUM(QTY) DESC
  

Sum_qty Столбец, очевидно, можно удалить