Dies ist eine typische Pivot-Transformation und bedingte Aggregation, wie von Phil vorgeschlagen , ist die gute alte Art, sie zu implementieren.
Es gibt auch eine modernere Syntax, um dasselbe Ergebnis zu erzielen, die die PIVOT-Klausel verwendet:
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
;
Intern entspricht diese wohl einfacher aussehende Syntax Phils GROUP BY-Abfrage. Genauer gesagt entspricht es dieser Variante:
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
;
Eine PIVOT-Abfrage ist also im Wesentlichen eine implizite GROUP BY-Abfrage.
PIVOT-Abfragen sind jedoch bekanntermaßen schwieriger zu verarbeiten als explizite GROUP BY-Abfragen mit bedingter Aggregation. Wenn Sie PIVOT verwenden, müssen Sie immer Folgendes beachten:
- Alle (
Claims
in diesem Fall) geschwenkten Spalten des Datasets, die in der PIVOT-Klausel nicht explizit erwähnt werden, sind GROUP BY-Spalten .
Wenn Claims
in Ihrem Beispiel nur drei Spalten angezeigt werden, funktioniert die obige PIVOT-Abfrage anscheinend wie erwartetCompanyName
die einzige in PIVOT nicht explizit erwähnte Spalte ist und somit das einzige Kriterium für die implizite GROUP BY ist.
Wenn Claims
jedoch andere Spalten vorhanden sind (z. B. ClaimDate
), werden diese implizit als zusätzliche GROUP BY-Spalten verwendet. Dies ist im Wesentlichen die Aufgabe Ihrer Abfrage
GROUP BY CompanyName, ClaimDate, ... /* whatever other columns there are*/`
Das Ergebnis wird höchstwahrscheinlich nicht das sein, was Sie wollen.
Das ist jedoch leicht zu beheben. Um irrelevante Spalten von der Teilnahme an der impliziten Gruppierung auszuschließen, können Sie einfach eine abgeleitete Tabelle verwenden, in der Sie nur die für das Ergebnis erforderlichen Spalten auswählen, obwohl die Abfrage dadurch weniger elegant aussieht:
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
;
Trotzdem, wenn Claims
es sich jedoch bereits um eine abgeleitete Tabelle handelt, muss keine weitere Verschachtelungsebene hinzugefügt werden. Stellen Sie lediglich sicher, dass Sie in der aktuellen abgeleiteten Tabelle nur die Spalten auswählen, die für die Ausgabe erforderlich sind.
Weitere Informationen zu PIVOT finden Sie im Handbuch: