web-dev-qa-db-fra.com

Instruction SQL GROUP BY CASE avec fonction d'agrégation

J'ai une colonne qui ressemble à quelque chose comme ça:

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

Et je voudrais le mettre dans ma clause GROUP BY, mais cela semble poser problème car il y a une fonction d'agrégat dans la colonne. Est-il possible de GROUPER un alias de colonne tel que some_product dans ce cas, ou dois-je mettre cela dans une sous-requête et un groupe sur cela?

40
Bryan Ward

Je suppose que vous ne voulez pas vraiment GROUP BY quelque_produit.

Le answer to: "Y a-t-il un moyen de GROUP BY un alias de colonne tel que some_product dans ce cas, ou dois-je placer cela dans une sous-requête et un groupe? "is: Vous ne pouvez pas GROUP BY un alias de colonne.

La clause SELECT, où les alias de colonne sont attribués, n'est pas traitée avant le GROUP BY clause. Une vue en ligne ou une expression de table commune (CTE) peut être utilisée pour rendre les résultats disponibles pour le regroupement.

Vue en ligne:

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 ... 
50
Shannon Severance

Bien que la réponse de Shannon soit techniquement correcte, cela ressemble à une overkill.

La solution simple est que vous devez placer votre sommation en dehors de l'instruction case. Cela devrait faire l'affaire:

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

En gros, votre ancien code indique à SQL d’exécuter la sum(X*Y) pour chaque ligne individuellement (en laissant à chaque ligne sa propre réponse qui ne peut pas être groupée).

La ligne de code que j'ai écrite prend le produit somme, qui est ce que vous voulez.

34
user2076246

Si vous regroupez par une autre valeur, alors au lieu de ce que vous avez,

l'écrire comme

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

Si, otoh, vous voulez group By l'expression interne, (col3*col4) puis

écris le group By pour correspondre à l'expression sans le 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 

Enfin, si vous souhaitez grouper par l'agrégat actuel

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
2
Charles Bretana