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 |
अफसोस की बात है कि पंक्ति 4 को पूरी तरह से समाप्त कर दिया गया है क्योंकि इसमें केवल NULLs हैं! स्रोत क्वेरी में डमी मान इंजेक्ट करके इसे फिर से शुरू किया जा सकता है:
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;
आईडी पर पंक्तियों को एकत्र करके हम गैर-शून्य मानों को गिन सकते हैं। स्रोत तालिका में कुल स्तंभों की तुलना में एक या अधिक 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
+ 1 में इंजेक्शन डमी कॉलम के लिए कॉलम की संख्या के रूप में 3 की गणना करता हूं
- आईडी के लिए 1, जो कि असमान नहीं है
कैटलॉग तालिकाओं की जांच करके यह मान रनटाइम पर प्राप्त किया जा सकता है।
परिणामों में शामिल होकर मूल पंक्तियों को पुनः प्राप्त किया जा सकता है।
यदि NULL से इतर मूल्यों की जांच की जानी है तो उन्हें एक खंड में शामिल किया जा सकता है:
...
) as unpvt
where ColValue <> '' -- will eliminate empty strings
विचार-विमर्श
इसके लिए एक पहचानकर्ता की आवश्यकता होती है जो UNPIVOT के माध्यम से किया जाता है। एक चाबी सबसे अच्छी होगी। यदि कोई भी मौजूद नहीं है तो ROW_NUMBER () विंडो फ़ंक्शन द्वारा इंजेक्ट किया जा सकता है , हालांकि इसे निष्पादित करना महंगा हो सकता है।
सभी कॉलम स्पष्ट रूप से UNPIVOT क्लॉज के अंदर सूचीबद्ध होने चाहिए। SSMS का उपयोग करके उन्हें घसीटा जा सकता है, जैसा कि @ db2 ने सुझाव दिया है। जब डायन परिभाषा दी जाएगी तो यह गतिशील नहीं होगा, क्योंकि हारून बर्ट्रेंड का सुझाव होगा। हालाँकि लगभग सभी SQL के लिए यही स्थिति है।
मेरे बजाय सीमित डेटा सेट के लिए निष्पादन योजना एक क्लस्टर इंडेक्स स्कैन और एक स्ट्रीम एग्रीगेट है। यह टेबल के सीधे स्कैन और बहुत सारे OR क्लॉज की तुलना में मेमोरी की अधिक महंगी होगी।