#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
Столбец, очевидно, можно удалить