Це типова стрижнева трансформація, і умовне агрегування, як запропонував Філ , є старим хорошим способом його здійснення.
Існує також більш сучасний синтаксис досягнення того ж результату, який використовує пункт 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 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, вам завжди потрібно пам’ятати про це одне:
- Усі стовпці набору даних, що переводяться (
Claims
у даному випадку), які чітко не вказані у пункті PIVOT, є стовпцями GROUP BY .
Якщо Claims
складається лише з трьох стовпців, показаних у вашому прикладі, запит 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 можна прочитати в посібнику: