Оператор SQL GROUP BY CASE с агрегатной функцией - PullRequest
38 голосов
/ 30 июля 2009

У меня есть столбец, который выглядит примерно так:

CASE
    WHEN col1 > col2 THEN SUM(col3*col4)
    ELSE 0
END AS some_product

И я хотел бы поместить его в мое предложение GROUP BY, но, похоже, это вызывает проблемы, поскольку в столбце есть агрегатная функция. Есть ли способ GROUP BY для псевдонима столбца, такого как some_product в этом случае, или мне нужно поместить это в подзапрос и группу для этого?

Ответы [ 3 ]

48 голосов
/ 31 июля 2009

Я предполагаю, что вы не хотите GROUP BY some_product.

Ответ на:"Есть ли способ GROUP BY псевдоним столбца, такой как some_product в этом случае, или мне нужно поместить это в подзапрос и сгруппировать по нему? is: Вы не можете GROUP BY псевдоним столбца.

Предложение SELECT, в котором присваиваются псевдонимы столбцов, не обрабатывается до окончания предложения GROUP BY. Можно использовать встроенное представление или общее табличное выражение (CTE), чтобы сделать результаты доступными для группировки.

Встроенный вид:

select ...
from (select ... , CASE WHEN col1 > col2 THEN SUM(col3*col4) ELSE 0 END AS some_product
   from ...
   group by col1, col2 ... ) T
group by some_product ...

CTE:

with T as (select ... , CASE WHEN col1 > col2 THEN SUM(col3*col4) ELSE 0 END AS some_product
   from ...
   group by col1, col2 ... )
select ...
from T
group by some_product ... 
34 голосов
/ 15 февраля 2013

Хотя ответ Шеннона технически верен, он выглядит излишним.

Простое решение заключается в том, что вам нужно поместить суммирование вне оператора case. Это должно сделать трюк:

sum(CASE WHEN col1 > col2 THEN col3*col4 ELSE 0 END) AS some_product

По сути, ваш старый код указывает SQL на выполнение sum(X*Y) для каждой строки отдельно (оставляя каждую строку со своим собственным ответом, который нельзя сгруппировать).

В строке кода, которую я написал, берется сумма, которая вам нужна.

2 голосов
/ 30 июля 2009

Если вы группируете по другому значению, то вместо того, что у вас есть,

напишите как

Sum(CASE WHEN col1 > col2 THEN SUM(col3*col4) ELSE 0 END) as SumSomeProduct

Если, ооо, вы хотите group By внутреннее выражение, (col3*col4), тогда

напишите group By, чтобы соответствовать выражению без SUM ...

Select Sum(Case When col1 > col2 Then col3*col4 Else 0 End) as SumSomeProduct
From ...

Group By Case When col1 > col2 Then col3*col4 Else 0 End 

Наконец, если вы хотите сгруппировать по фактической совокупности

Select SumSomeProduct, Count(*), <other aggregate functions>
From (Select <other columns you are grouping By>, 
      Sum(Case When col1 > col2 
          Then col3*col4 Else 0 End) as SumSomeProduct
      From Table
      Group By <Other Columns> ) As Z
Group by SumSomeProduct
...