UNPIVOT menerjemahkan kolom menjadi baris. Dalam prosesnya menghilangkan nilai NULL ( referensi ).
Diberikan input
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);
permintaan 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;
akan menghasilkan output
| ID | ColName | ColValue |
|----|---------|----------|
| 1 | c1 | 12 |
| 1 | c2 | 13 |
| 2 | c2 | 14 |
| 3 | c1 | 15 |
Sayangnya baris 4 telah dihilangkan seluruhnya karena hanya memiliki NULL! Itu dapat dengan mudah diperkenalkan kembali dengan menyuntikkan nilai dummy ke dalam kueri sumber:
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;
Dengan menjumlahkan baris pada ID kita dapat menghitung nilai-nilai yang bukan nol. Perbandingan dengan jumlah total kolom dalam tabel sumber akan mengidentifikasi baris yang berisi satu atau lebih 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;
Saya menghitung 3 sebagai
jumlah kolom dalam tabel sumber #t
+ 1 untuk kolom dummy yang disuntikkan
- 1 untuk ID, yang tidak UNPIVOTED
Nilai ini dapat diperoleh saat runtime dengan memeriksa tabel katalog.
Baris asli dapat diambil dengan bergabung ke hasilnya.
Jika nilai selain NULL ingin diselidiki, nilai itu dapat dimasukkan dalam klausa where:
...
) as unpvt
where ColValue <> '' -- will eliminate empty strings
Diskusi
Ini membutuhkan pengenal yang dilakukan melalui UNPIVOT. Kunci akan menjadi yang terbaik. Jika tidak ada, dapat disuntikkan oleh ROW_NUMBER () fungsi jendela , meskipun ini mungkin mahal untuk dieksekusi.
Semua kolom harus dicantumkan secara eksplisit di dalam klausa UNPIVOT. Mereka dapat diseret menggunakan SSMS, seperti yang disarankan @ db2. Itu tidak akan dinamis ketika definisi tabel chagnes, seperti saran Aaron Bertrand. Ini adalah kasus untuk hampir semua SQL.
Untuk set data saya yang agak terbatas, rencana eksekusi adalah scan indeks berkerumun dan agregat aliran. Memori ini akan lebih mahal daripada pemindaian langsung tabel dan banyak klausa ATAU.