UNPIVOT dịch các cột thành hàng. Trong quá trình nó loại bỏ các giá trị NULL ( tham chiếu ).
Đưa ra đầu vào
create table #t
(
ID int primary key,
c1 int null,
c2 int null
);
insert #t(id, c1, c2)
values
(1, 12, 13),
(2, null, 14),
(3, 15, null),
(4, null, null);
truy vấn UNPIVOT
select
ID, ColName, ColValue
from
(
select *
from #t
) as p
unpivot
(
ColValue for ColName in
(c1, c2) -- explicit source column names required
) as unpvt;
sẽ tạo ra đầu ra
| ID | ColName | ColValue |
|----|---------|----------|
| 1 | c1 | 12 |
| 1 | c2 | 13 |
| 2 | c2 | 14 |
| 3 | c1 | 15 |
Đáng buồn là hàng 4 đã bị loại bỏ hoàn toàn vì nó chỉ có NULL! Nó có thể được giới thiệu lại một cách thuận tiện bằng cách đưa một giá trị giả vào truy vấn nguồn:
select
ID, ColName, ColValue
from
(
select
-5 as dummy, -- injected here, -5 is arbitrary
*
from #t
) as p
unpivot
(
ColValue for ColName in
(dummy, c1, c2) -- referenced here
) as unpvt;
Bằng cách tổng hợp các hàng trên ID, chúng ta có thể đếm các giá trị khác null. So sánh với tổng số cột trong bảng nguồn sẽ xác định các hàng có chứa một hoặc nhiều NULL.
select
ID
from
(
select -5 as dummy, *
from #t
) as p
unpivot
(
ColValue for ColName in
(dummy, c1, c2)
) as unpvt
group by ID
having COUNT(*) <> 3;
Tôi tính 3 là
số cột trong bảng nguồn #t
+ 1 cho cột giả được chèn
- 1 cho ID, không được UNPIVOTED
Giá trị này có thể đạt được khi chạy bằng cách kiểm tra các bảng danh mục.
Các hàng ban đầu có thể được lấy bằng cách tham gia vào kết quả.
Nếu các giá trị khác ngoài NULL được điều tra, chúng có thể được bao gồm trong mệnh đề where:
...
) as unpvt
where ColValue <> '' -- will eliminate empty strings
Thảo luận
Điều này đòi hỏi một định danh được thực hiện thông qua UNPIVOT. Một chìa khóa sẽ là tốt nhất. Nếu không tồn tại, có thể được chèn bởi hàm cửa sổ ROW_NUMBER () , mặc dù điều này có thể tốn kém để thực thi.
Tất cả các cột phải được liệt kê rõ ràng bên trong mệnh đề UNPIVOT. Chúng có thể được kéo vào bằng cách sử dụng SSMS, như @ db2 đề xuất. Nó sẽ không năng động khi định nghĩa bảng chagnes, như đề xuất của Aaron Bertrand sẽ là. Đây là trường hợp cho hầu hết tất cả SQL, tuy nhiên.
Đối với dữ liệu khá hạn chế của tôi, kế hoạch thực hiện là quét chỉ mục cụm và tổng hợp luồng. Điều này sẽ tốn bộ nhớ hơn so với việc quét thẳng bảng và nhiều mệnh đề OR.