यदि कोई कॉलम NULL है तो परीक्षण करें


16

मैं एक आसान क्वेरी का पता लगाने की कोशिश कर रहा हूं, अगर मैं परीक्षण कर सकता हूं कि किसी बड़ी तालिका में किसी भी स्तंभ में कम से कम एक रिक्त (NULL / खाली) मान वाली प्रविष्टियों की एक सूची है।

मुझे कुछ चाहिए

SELECT * FROM table AS t WHERE ANY(t.* IS NULL)

मुझे नहीं करना है

SELECT * FROM table AS t WHERE t.c1 = NULL OR t.c2 = NULL OR t.c3 = NULL

यह एक बड़ी क्वेरी होगी।

जवाबों:


16

कम के साथ @ db2 के उत्तर के लिए एक एक्सटेंशन (पढ़ें: शून्य) हाथ से काम करना:

DECLARE @tb nvarchar(512) = N'dbo.[table]';

DECLARE @sql nvarchar(max) = N'SELECT * FROM ' + @tb
    + ' WHERE 1 = 0';

SELECT @sql += N' OR ' + QUOTENAME(name) + ' IS NULL'
    FROM sys.columns 
    WHERE [object_id] = OBJECT_ID(@tb);

EXEC sys.sp_executesql @sql;

8

आपको जेएनके की टिप्पणी के अनुसार सभी कॉलमों को सूचीबद्ध करना चाहिए।

WHERE c1 IS NULL OR c2 IS NULL OR c3 IS NULL

कुछ हद तक कम कुशल दृष्टिकोण जो इससे बचता है, हालांकि नीचे है।

;WITH xmlnamespaces('http://www.w3.org/2001/XMLSchema-instance' AS ns) 
SELECT * 
FROM   YourTable AS T1 
WHERE (
    SELECT T1.* 
    FOR XML PATH('row'), ELEMENTS XSINIL, TYPE
  ).exist('//*/@ns:nil') = 1 

(इस एसओ जवाब पर आधारित)


5

कोई अच्छा अंतर्निहित सिंटैक्स नहीं है, लेकिन क्वेरी को जल्दी से उत्पन्न करने के लिए प्रबंधन स्टूडियो में कुछ सुविधाजनक सुविधाएँ हैं।

ऑब्जेक्ट एक्सप्लोरर में, इच्छित तालिका के नीचे ड्रिल करें, इसे विस्तारित करें, फिर पूरे "कॉलम" फ़ोल्डर को एक खाली क्वेरी संपादक में खींचें। यह कॉलम में अल्पविराम से अलग की गई सूची को क्वेरी में जोड़ देगा।

इसके बाद फाइंड एंड रिप्लेस को ओपन करें। "खोजें क्या" ,सेट करें और "बदलें" के साथ सेट करेंIS NULL OR एक प्रमुख स्थान के फिर सभी को बदलें। आपको हाथ से पिछले एक को साफ करना होगा।

यह अभी भी बदसूरत है, लेकिन यह कम श्रम गहन बदसूरत है।


4

के लिए एकाधिक समाधान: कुछ नल, सभी नल, एकल और कई कॉलम प्लस इसे शीर्ष 1 का उपयोग करके क्विक बनाते हैं

यदि आपको कई स्तंभों का परीक्षण करने की आवश्यकता है, तो आप निम्नलिखित का उपयोग कर सकते हैं:

Column_1 Column_2 Column_3
-------- -------- --------
1        2        NULL
1        NULL     NULL
5        6        NULL

सबसे पहले , NULLs का परीक्षण करें और उन्हें गिनें:

select 
    sum(case when Column_1 is null then 1 else 0 end) as Column_1, 
    sum(case when Column_2 is null then 1 else 0 end) as Column_2, 
    sum(case when Column_3 is null then 1 else 0 end) as Column_3,
from TestTable 

NULLs की संख्या प्राप्त करता है:

Column_1  Column_2  Column_3
0         1         3

जहाँ परिणाम 0 है, वहाँ कोई NULLs नहीं हैं।

दूसरा , गैर-पूर्ण गणना करें:

select 
    sum(case when Column_1 is null then 0 else 1 end) as Column_1, 
    sum(case when Column_2 is null then 0 else 1 end) as Column_2, 
    sum(case when Column_3 is null then 0 else 1 end) as Column_3,
from TestTable

... लेकिन क्योंकि हम यहाँ गैर-नल की गिनती कर रहे हैं, इसे सरल बनाया जा सकता है:

select 
    count(Column_1) as Column_1, 
    count(Column_2) as Column_2, 
    count(Column_3) as Column_3,
from TestTable

या तो एक पैदावार:

Column_1  Column_2  Column_3
3         2         0

जहां परिणाम 0 है, स्तंभ पूरी तरह से NULLs से बना है।

अंत में , यदि आपको केवल एक विशिष्ट कॉलम की जांच करनी है, तो TOP 1 तेज है क्योंकि इसे पहले हिट पर रोकना चाहिए। फिर आप बूलियन-स्टाइल परिणाम देने के लिए वैकल्पिक रूप से गिनती (*) का उपयोग कर सकते हैं:

select top 1 'There is at least one NULL' from TestTable where Column_3 is NULL

select count(*) from (select top 1 'There is at least one NULL' AS note from TestTable where Column_3 is NULL) a

0 = कोई NULLs नहीं हैं, 1 = कम से कम एक NULL है

या

select top 1 'There is at least one non-NULL' AS note from TestTable where Column_3 is not NULL

select count(*) from (select top 1 'There is at least one non-NULL' AS note from TestTable where Column_3 is not NULL) a

0 = वे सभी NULL हैं, 1 = कम से कम एक गैर-NULL है

आशा है कि ये आपकी मदद करेगा।


हालांकि यह काफी उपयोगी लगता है, मुझे यह ध्यान देना एक दायित्व लगता है कि यह वह नहीं है जो ओपी पूछ रहा था - वे प्रत्येक पंक्ति की सामग्री चाहते थे जिसमें एक NULL मान शामिल हो, न कि केवल यह देखने के लिए कि कोई मौजूद है।
RDFozz

काफी उचित। मुझे लगता है कि मैं इसे अलग तरीके से पढ़ रहा था। मैं "... परीक्षण पर ध्यान केंद्रित किया गया था अगर एक बड़ी मेज है ..." भाग, इसलिए ... बूलियन (मेरे मामले में बूलियन-ईश)। लेकिन अगर, "प्रविष्टियों की सूची" से उनका मतलब पंक्तियों से है, तो आप बिल्कुल सही हैं।
jwolf

बस इस पर दोबारा गौर किया। मैंने निश्चित रूप से प्रश्न का गलत अर्थ निकाला - यह अनुमान लगाना चाहिए कि वह परिणाम के रूप में पंक्तियों की तलाश कर रहा था। मुझे लगता है कि मुझे यह भी गलत लगता है कि उसके पास विशाल का क्या मतलब है। मैंने मूल रूप से सोचा था कि वह कम्प्यूटेशनल रूप से महंगा था, लेकिन अब मुझे लगता है कि वह स्तंभों के साथ विस्तृत था, इसलिए एरॉन और DB2 को यह सही लगा, पढ़ने और समाधान दोनों में (जिसके आधार पर अधिक थका हुआ है: आपका मस्तिष्क या आपकी उंगलियां)
jwolf

2

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 क्लॉज की तुलना में मेमोरी की अधिक महंगी होगी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.