これは典型的なピボット変換であり、Philが示唆するように、条件付き集約はそれを実装する古き良き方法です。
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
;
内部的には、このほぼ間違いなくシンプルな構文は、PhilのGROUP BYクエリと同等です。より正確には、このバリエーションと同等です。
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
;
したがって、PIVOTクエリは、本質的に暗黙のGROUP BYクエリです。
ただし、PIVOTクエリは、条件付き集計を使用した明示的なGROUP BYクエリよりも処理が難しいことで有名です。PIVOTを使用している場合、次の1つを常に念頭に置く必要があります。
Claims
PIVOT句で明示的に言及されていない(この場合)ピボットされるデータセットのすべての列はGROUP BY列です。
場合はClaims
期待どおりの例に示す3つの列のみ、意志の仕事上のPIVOTクエリで構成され、理由は明らかにCompanyName
唯一の列には、明示的PIVOTで言及されていないため、暗黙のGROUP BYの唯一の基準として終わります。
ただし、Claims
他の列がある場合(などClaimDate
)、それらは追加のGROUP BY列として暗黙的に使用されます。つまり、クエリは基本的に
GROUP BY CompanyName, ClaimDate, ... /* whatever other columns there are*/`
結果はおそらくあなたが望むものではないでしょう。
ただし、これは簡単に修正できます。関係のない列を暗黙的なグループ化に参加させないようにするには、結果に必要な列のみを選択する派生テーブルを使用できますが、クエリの見栄えが悪くなります。
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
;
それでも、Claims
既に派生テーブルである場合は、別のレベルのネストを追加する必要はありません。現在の派生テーブルでは、出力の生成に必要な列のみを選択していることを確認してください。
PIVOTの詳細については、マニュアルをご覧ください。