UNPIVOT แปลคอลัมน์เป็นแถว ในกระบวนการมันกำจัดค่า NULL ( อ้างอิง )
รับอินพุต
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);
แบบสอบถาม 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;
จะผลิตผลลัพธ์
| ID | ColName | ColValue |
|----|---------|----------|
| 1 | c1 | 12 |
| 1 | c2 | 13 |
| 2 | c2 | 14 |
| 3 | c1 | 15 |
Sadly row 4 ถูกกำจัดออกไปอย่างสิ้นเชิงเนื่องจากมันมีค่า NULL เท่านั้น! สามารถนำมาใช้ใหม่ได้โดยสะดวกโดยการฉีดค่าดัมมี่ลงในคิวรีแหล่งข้อมูล:
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;
ด้วยการรวมแถวใน ID เราสามารถนับค่าที่ไม่เป็นนัล การเปรียบเทียบกับจำนวนคอลัมน์ทั้งหมดในตารางต้นฉบับจะระบุแถวที่มีค่า 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;
ฉันคำนวณ 3 เป็น
จำนวนคอลัมน์ในตารางต้นฉบับ #t
+ 1 สำหรับคอลัมน์ดัมมีการฉีด
- 1 สำหรับ ID ซึ่งไม่ใช่ UNPIVOTED
สามารถรับค่านี้ได้ในขณะทำงานโดยตรวจสอบตารางแคตตาล็อก
แถวเดิมสามารถดึงได้โดยเข้าร่วมกับผลลัพธ์
หากค่าอื่นที่ไม่ใช่ NULL จะถูกตรวจสอบพวกเขาสามารถรวมอยู่ในส่วนคำสั่ง:
...
) as unpvt
where ColValue <> '' -- will eliminate empty strings
อภิปรายผล
สิ่งนี้ต้องการตัวระบุที่ดำเนินการผ่าน UNPIVOT กุญแจจะดีที่สุด หากไม่มีใครสามารถใช้ฟังก์ชันหน้าต่างROW_NUMBER ()ได้ แต่อาจมีค่าใช้จ่ายสูงในการดำเนินการ
คอลัมน์ทั้งหมดจะต้องอยู่ในรายการอย่างชัดเจนในข้อ UNPIVOT พวกเขาสามารถลากโดยใช้ SSMS ตามที่แนะนำ @ db2 มันจะไม่เป็นแบบไดนามิกเมื่อความหมายของตาราง chagnes ตามคำแนะนำของแอรอนเบอร์ทรานด์จะเป็น อย่างไรก็ตามนี่เป็นกรณีของ SQL เกือบทั้งหมด
สำหรับชุดข้อมูลที่ค่อนข้าง จำกัด ของฉันแผนการดำเนินการคือการสแกนดัชนีแบบคลัสเตอร์และกระแสรวม สิ่งนี้จะมีราคาแพงกว่าหน่วยความจำมากกว่าการสแกนตารางและคำสั่ง OR จำนวนมาก