2009-07-30 44 views
34

tengo una columna que se ve algo como esto:instrucción CASE SQL GROUP BY con función de agregado

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

Y me gustaría ponerlo en mi cláusula GROUP BY, pero esto parece causar problemas porque no hay una función agregada en la columna. ¿Hay alguna manera de AGRUPAR un alias de columna como some_product en este caso, o debo poner esto en una subconsulta y un grupo sobre eso?

Respuesta

41

Mi conjetura es que usted realmente no quiere GROUP BY some_product.

El respuesta a: "? ¿Hay una manera de GROUP BY un alias de columna como some_product en este caso, o tengo que poner esto en una sub consulta y el grupo en el que" es: No se puede GROUP BY un alias de columna.

La cláusula SELECT, donde se asignan los alias de columna, no se procesa hasta después de la cláusula GROUP BY. Se podría usar una vista en línea o expresión de tabla común (CTE) para hacer que los resultados estén disponibles para la agrupación.

Ver incluido:

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

Este es un gran ejemplo de cómo usar un CTE . –

1

Si está agrupando por algún otro valor, en lugar de lo que tienes,

escritura como

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

Si, Otoh, desea group By la expresión interna, (col3*col4) continuación

escribir la group By para que coincida con la expresión w/o la 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 

Por último, si desea agrupar por el agregado real

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

Agregas * a * una agrupación. No * en * la agrupación. – gbn

+0

Quien haya votado, está equivocado. Intenta algo similar tú mismo ... "dame la suma de 2 valores multiplicados, agrupados por otros 2 valores, y también agrupados en el agregado de mi grupo". – gbn

+0

Después de la edición de Charles: su consulta interna solo devolverá una fila, haciendo que su agrupación externa carezca de sentido ... – gbn

27

Mientras Shannon's answer es técnicamente correcto, se ve como un exceso.

La solución simple es que debe colocar su suma fuera de la declaración case. Esto debería hacer el truco:

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

Básicamente, su antiguo código indica a SQL para ejecutar la sum(X*Y) individualmente para cada línea (dejando a cada uno de acuerdo con su propia respuesta que no se pueden agrupar).

La línea de código que he escrito toma la suma del producto, que es lo que desea.

+0

¿Hay alguna razón por la que no desee utilizar este método sobre la respuesta de Shannon que implica un CTE? Gracias – Gareth

+0

Para las declaraciones de casos generales, querrá usar la respuesta de Shannon. Este se basa en sumas de 0 que son 0. – coberlin