2009-07-30 17 views
34

Mam kolumnę, która wygląda mniej więcej tak:SQL GROUP BY case z zagregowanej funkcji

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

i chciałbym, aby umieścić go w moim klauzuli GROUP BY, ale to wydaje się być przyczyną problemów, ponieważ nie ma funkcja agregująca w kolumnie. Czy istnieje sposób na GROUP BY z takim aliasem kolumnowym, jak some_product w tym przypadku, czy też muszę umieścić to w podzapytaniu i grupie?

Odpowiedz

41

Domyślam się, że tak naprawdę nie chcą GROUP BY some_product.

odpowiedź: „? Czy istnieje sposób GROUP BY alias kolumny takie jak some_product w tym przypadku, czy muszę umieścić to w podkwerendzie i grupy na tym” to: Nie można GROUP BY aliasu kolumny.

Klauzula SELECT, do której przypisywane są aliasy kolumn, nie jest przetwarzana przed klauzulą ​​GROUP BY. Aby wyniki były dostępne dla grupowania, można użyć widoku śródliniowego lub wspólnego wyrażenia tabelowego (CTE).

Inline widok:

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 ... 
+1

To jest świetny przykład jak używać CTE . –

1

Jeśli grupowanie przez inną wartość, to zamiast tego, co masz,

zapisać go jako

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

Jeżeli OTOH, chcesz group By wyraz wewnętrznego (col3*col4) następnie

wpisz group By, aby dopasować wyrażenie z 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 

Wreszcie, jeśli chcesz grupy przez rzeczywistą kruszywa

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 
+0

Sumujesz * powyżej * grupowania. Nie * w * grupie. – gbn

+0

Ktokolwiek wziął udział, jest zły. Spróbuj czegoś podobnego samemu ... "podaj sumę 2 wartości pomnożonych, pogrupowanych według 2 innych wartości, a także grupuj w agregacie mojej grupy". – gbn

+0

Po edycji Charlesa: Twoja wewnętrzna kwerenda zwróci tylko jeden wiersz, dzięki czemu twoja zewnętrzna grupa będzie pozbawiona znaczenia ... – gbn

27

Podczas Shannon's answer jest technicznie poprawne, wygląda na to przesada.

Najprostszym rozwiązaniem jest umieszczenie podsumowania na zewnątrz oświadczenia case. To powinno załatwić sprawę:

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

Zasadniczo mówi twój stary kod SQL do wykonania sum(X*Y) dla każdej linii osobno (pozostawiając każdą linię własnej odpowiedzi, które nie mogą być pogrupowane).

Linia kodu, którą napisałem, bierze produkt sumaryczny, który jest tym, co chcesz.

+0

Czy istnieje jakikolwiek powód, dla którego nie chciałbyś użyć tej metody zamiast odpowiedzi Shannona dotyczącej CTE? Dzięki – Gareth

+0

W przypadku ogólnych instrukcji dotyczących spraw, chciałbyś użyć odpowiedzi Shannona. Ten opiera się na sumach 0 jako 0. – coberlin