2009-07-30 16 views
34

Ho una colonna che sembra qualcosa di simile:SQL GROUP BY istruzione CASE con funzione di aggregazione

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

E vorrei metterlo nel mio clausola GROUP BY, ma questo sembra causare problemi perché non c'è una funzione aggregata in colonna. C'è un modo per raggruppare un alias di colonna come some_product in questo caso, o devo metterlo in una sottoquery e raggruppare su quello?

risposta

41

La mia ipotesi è che non si ha realmente desidera GROUP BY some_product.

La risposta: "? C'è un modo per GROUP BY un alias di colonna, come some_product in questo caso, o ho bisogno di mettere questo in una sottoquery e di gruppo su quella" è: Non è possibile aggiungere un alias alla colonna GROUP BY.

La clausola SELECT, in cui gli alias di colonna sono assegnati, non viene elaborata fino a dopo la clausola GROUP BY. Una vista in linea o un'espressione di tabella comune (CTE) potrebbe essere utilizzata per rendere i risultati disponibili per il raggruppamento.

vista in linea:

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

Questo è un ottimo esempio di come usare un CTE . –

1

Se si esegue il raggruppamento per qualche altro valore, allora invece di quello che hai,

scrivo come

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

Se, OTOH, si vuole group By l'espressione interna, (col3*col4) poi

scrivere il group By per abbinare l'espressione senza il 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 

Infine, se si desidera raggruppare dall'aggregato attuale

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

Si aggrega * su * un raggruppamento. Non * su * il raggruppamento. – gbn

+0

Chi ha svalutato, è sbagliato. Prova tu stesso qualcosa di simile ... "dammi la somma di 2 valori moltiplicati, raggruppati per 2 altri valori, e anche raggruppare sull'aggregato del mio gruppo". – gbn

+0

Dopo la modifica di Charles: la tua query interna restituirà sempre una riga, rendendo il tuo raggruppamento esterno privo di significato ... – gbn

27

Mentre Shannon's answer è tecnicamente corretto, sembra eccessivo.

La soluzione semplice è che è necessario inserire la sommatoria al di fuori dell'istruzione case. Questo dovrebbe fare il trucco:

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

In sostanza, il vecchio codice indica a SQL per eseguire il sum(X*Y) per ogni linea singolarmente (lasciando ogni linea con la propria risposta che non può essere raggruppate).

La riga di codice che ho scritto prende la somma del prodotto, che è ciò che si desidera.

+0

C'è qualche ragione per cui non si vorrebbe usare questo metodo sulla risposta di Shannon che coinvolge un CTE? Grazie – Gareth

+0

Per le dichiarazioni generali di casi, vorresti usare la risposta di Shannon. Questo si basa su somme da 0 a 0. – coberlin

Problemi correlati