Esta es una transformación pivote típica, y la agregación condicional, como lo sugirió Phil , es la buena forma de implementarla.
También hay una sintaxis más moderna para lograr el mismo resultado, que utiliza la cláusula PIVOT:
SELECT
CompanyName,
TotalOpenClaims = [1],
TotalClosedClaims = [2],
TotalReOpenedClaims = [3],
TotalPendingClaims = [4]
FROM
dbo.Claims
PIVOT
(
COUNT(ClaimID)
FOR StatusID IN ([1], [2], [3], [4])
) AS p
;
Internamente, esta sintaxis de apariencia más simple es equivalente a la consulta GROUP BY de Phil. Más exactamente, es equivalente a esta variación:
SELECT
CompanyName,
TotalOpenClaims = COUNT(CASE WHEN StatusID = 1 THEN ClaimID END),
TotalClosedClaims = COUNT(CASE WHEN StatusID = 2 THEN ClaimID END),
TotalReOpenedClaims = COUNT(CASE WHEN StatusID = 3 THEN ClaimID END),
TotalPendingClaims = COUNT(CASE WHEN StatusID = 4 THEN ClaimID END)
FROM
dbo.Claims
GROUP BY
CompanyName
;
Entonces, una consulta PIVOT es esencialmente una consulta GROUP BY implícita.
Sin embargo, las consultas PIVOT son notoriamente más difíciles de manejar que las consultas explícitas GROUP BY con agregación condicional. Cuando usa PIVOT, siempre debe tener en cuenta lo siguiente:
- Todas las columnas del conjunto de datos que se pivotan (
Claims
en este caso) que no se mencionan explícitamente en la cláusula PIVOT son columnas GROUP BY .
Si Claims
consta solo de las tres columnas que se muestran en su ejemplo, la consulta PIVOT anterior funcionará como se esperaba, porque aparentemente CompanyName
es la única columna que no se menciona explícitamente en PIVOT y, por lo tanto, termina siendo el único criterio del GROUP BY implícito.
Sin embargo, si Claims
tiene otras columnas (por ejemplo, ClaimDate
), se utilizarán implícitamente como columnas GROUP BY adicionales, es decir, su consulta esencialmente estará haciendo
GROUP BY CompanyName, ClaimDate, ... /* whatever other columns there are*/`
El resultado probablemente no sea lo que quieres.
Sin embargo, eso es fácil de arreglar. Para excluir a las columnas irrelevantes de participar en la agrupación implícita, solo puede usar una tabla derivada, donde seleccionará solo las columnas necesarias para el resultado, aunque eso hace que la consulta tenga un aspecto menos elegante:
SELECT
CompanyName,
TotalOpenClaims = [1],
TotalClosedClaims = [2],
TotalReOpenedClaims = [3],
TotalPendingClaims = [4]
FROM
(SELECT ClaimID, CompanyName, StatusID FROM dbo.Claims) AS derived
PIVOT
(
COUNT(ClaimID)
FOR StatusID IN ([1], [2], [3], [4])
) AS p
;
Aún así, si Claims
ya es una tabla derivada, no es necesario agregar otro nivel de anidamiento, solo asegúrese de que en la tabla derivada actual esté seleccionando solo las columnas necesarias para producir el resultado.
Puede leer más sobre PIVOT en el manual: