Đây là một chuyển đổi trục điển hình và tổng hợp có điều kiện, như đề xuất của Phil , là cách tốt để thực hiện nó.
Ngoài ra còn có một cú pháp hiện đại hơn để đạt được kết quả tương tự, sử dụng mệnh đề 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
;
Trong nội bộ cú pháp tìm kiếm đơn giản hơn này có thể tương đương với truy vấn GROUP BY của Phil. Chính xác hơn, nó tương đương với biến thể này:
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
;
Vì vậy, về cơ bản, một truy vấn PIVOT là một truy vấn GROUP BY ẩn.
Tuy nhiên, các truy vấn PIVOT nổi tiếng là khó xử lý hơn các truy vấn GROUP BY rõ ràng với tổng hợp có điều kiện. Khi bạn đang sử dụng PIVOT, bạn cần luôn ghi nhớ điều này:
- Tất cả các cột của bộ dữ liệu được xoay vòng (
Claims
trong trường hợp này) không được đề cập rõ ràng trong mệnh đề PIVOT là các cột GROUP BY .
Nếu chỉ Claims
bao gồm ba cột được hiển thị trong ví dụ của bạn, truy vấn PIVOT ở trên sẽ hoạt động như mong đợi, vì rõ ràng CompanyName
là cột duy nhất không được đề cập rõ ràng trong PIVOT và do đó kết thúc là tiêu chí duy nhất của NHÓM ẩn.
Tuy nhiên, nếu Claims
có các cột khác (giả sử ClaimDate
), chúng sẽ hoàn toàn được sử dụng làm các cột NHÓM B BYNG bổ sung - nghĩa là, truy vấn của bạn về cơ bản sẽ được thực hiện
GROUP BY CompanyName, ClaimDate, ... /* whatever other columns there are*/`
Kết quả rất có thể sẽ không như những gì bạn muốn.
Đó là dễ dàng để sửa chữa, mặc dù. Để loại trừ các cột không liên quan tham gia vào nhóm ẩn, bạn chỉ có thể sử dụng bảng dẫn xuất, trong đó bạn sẽ chỉ chọn các cột cần thiết cho kết quả, mặc dù điều đó làm cho truy vấn trông kém thanh lịch:
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
;
Tuy nhiên, nếu Claims
đã là một bảng dẫn xuất, không cần thêm một mức lồng nhau khác, chỉ cần đảm bảo rằng trong bảng dẫn xuất hiện tại bạn chỉ chọn các cột cần thiết để tạo đầu ra.
Bạn có thể đọc thêm về PIVOT trong hướng dẫn: