Herhangi bir sütunun NULL olup olmadığını test edin


16

Ben büyük bir tablo HERHANGİ BİR sütunda en az bir boş (NULL / boş) değeri olan girdilerin bir listesi olup olmadığını test etmek için yapabileceğiniz kolay bir sorgu anlamaya çalışıyorum.

Gibi bir şeye ihtiyacım var

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

Yapmak zorunda değilim

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

Bu çok büyük bir sorgu olurdu.

Yanıtlar:


16

@ Db2'nin cevabının daha az el ile wrangling (okuma: sıfır) ile bir uzantısı:

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

Tüm sütunları JNK'nin yorumuna göre listelemelisiniz.

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

Ancak bundan kaçınan daha az verimli bir yaklaşım aşağıdadır.

;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 

(Bu SO cevabına dayanarak)


5

Güzel bir yerleşik sözdizimi yoktur, ancak Management Studio, sorguyu hızlı bir şekilde oluşturmak için birkaç kullanışlı özelliğe sahiptir.

Nesne Gezgini'nde istediğiniz tabloya gidin, genişletin ve ardından "Sütunlar" klasörünün tamamını boş bir sorgu düzenleyicisine sürükleyin. Bu, sorguya virgülle ayrılmış sütun listesi ekleyecektir.

Ardından, Bul ve Değiştir'i açın. ,"Aranan " ı ve "Şununla Değiştir" seçeneğiniIS NULL OR (baştaki boşlukla) olarak Tümünü Değiştir'e basın. Sekanstaki sonuncuyu elle temizlemeniz gerekir.

Hala çirkin, ama daha az emek yoğun çirkin.


4

İçin Çoklu Çözümler: bazı nulls, tüm nulls, tek ve çoklu sütunlar artı Top kullanarak HIZLI yapma 1

Birden fazla sütunu test etmeniz gerekiyorsa, aşağıdakileri kullanabilirsiniz:

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

İlk olarak , NULL'ları test edin ve sayın:

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 

Bir dizi NULL değeri verir:

Column_1  Column_2  Column_3
0         1         3

Sonucun 0 olduğu yerde NULL yoktur.

İkincisi , NULL olmayanları sayalım:

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

... Ama burada NULL olmayanları saydığımız için, bu basitleştirilebilir:

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

İkisinden biri:

Column_1  Column_2  Column_3
3         2         0

Sonuç 0 olduğunda, sütun tamamen NULL'lardan oluşur.

Son olarak , yalnızca belirli bir sütunu kontrol etmeniz gerekiyorsa, ilk vuruşta durması gerektiğinden TOP 1 daha hızlıdır. Ardından isteğe bağlı olarak boole stili bir sonuç vermek için count (*) kullanabilirsiniz:

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 = NULL yok, 1 = En az bir NULL var

veya

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 = Hepsi NULL, 1 = En az bir NULL olmayan var

Umarım bu yardımcı olur.


Bu oldukça yararlı görünse de, OP'nin istediği şey olmadığını belirtmek zorundayım - sadece var olup olmadığını görmek için bir kontrol değil, NULL değer içeren her satırın içeriğini istediler .
RDFozz

Yeterince adil. Sanırım sadece farklı okuyordum. Ben büyük bir tablonun ... ... testi olup olmadığına odaklandım, yani ... Boolean (benim durumumda Boolean-ish). Ancak, "girişler listesi" ile satırları kastediyorsa, kesinlikle haklısınız demektir.
jwolf

Bunu tekrar ziyaret ettim. Soruyu kesinlikle yanlış yorumladım - sonuç olarak satırları aradığını anlamalıydım. Bence onun BÜYÜK ne demek yanlış anlama. Başlangıçta hesaplamalı olarak pahalı olduğunu düşündüm ama şimdi sadece sütunlarla geniş olduğunu düşünüyorum, bu yüzden Arron ve DB2 hem okumada hem de çözümlerde doğru olanı (hangisinin daha yorgun olduğuna bağlı olarak: beyniniz veya parmaklarınız)
jwolf

2

UNPIVOT sütunları satırlara çevirir. Süreçte NULL değerleri ortadan kaldırır ( başvuru ) .

Girdi verildi

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 sorgusu

select
    ID, ColName, ColValue
from
(
    select *
    from #t
) as p
unpivot
(
    ColValue for ColName in
    (c1, c2)                  -- explicit source column names required
) as unpvt;

çıktı üretecek

| ID | ColName | ColValue |
|----|---------|----------|
| 1  | c1      | 12       |
| 1  | c2      | 13       |
| 2  | c2      | 14       |
| 3  | c1      | 15       |

Ne yazık ki 4. sıra sadece NULLs olduğu için tamamen elendi! Kaynak sorguya bir kukla değer enjekte ederek uygun şekilde yeniden eklenebilir:

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;

Kimlik üzerindeki satırları toplayarak null olmayan değerleri sayabiliriz. Kaynak tablodaki toplam sütun sayısıyla karşılaştırma, bir veya daha fazla NULL içeren satırları tanımlar.

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;

Enjekte edilen kukla sütun için
kaynak tablo #t
+ 1
- UNPIVOTED olmayan kimlik için 1 - sütun sayısını 3 olarak hesaplıyorum

Bu değer, çalışma zamanında katalog tabloları incelenerek elde edilebilir.

Orijinal satırlar, sonuçlara katılarak alınabilir.

NULL dışındaki değerler araştırılacaksa, bu değerler bir where yan tümcesine dahil edilebilir:

...
) as unpvt
where ColValue <> ''      -- will eliminate empty strings

Tartışma

Bu, UNPIVOT üzerinden taşınan bir tanımlayıcı gerektirir. Bir anahtar en iyisi olurdu. Hiçbiri yoksa, ROW_NUMBER () pencere işlevi tarafından enjekte edilebilir , ancak bunun yürütülmesi pahalı olabilir.

Tüm sütunlar açıkça UNPIVOT yan tümcesinde listelenmelidir. @ Db2'nin önerdiği gibi SSMS kullanılarak sürüklenebilirler. Aaron Bertrand'ın önerisi gibi, tablo tanımı tarandığında dinamik olmayacaktır. Bununla birlikte, hemen hemen tüm SQL'ler için durum böyledir.

Oldukça sınırlı veri setim için yürütme planı, kümelenmiş bir dizin taraması ve bir akış toplamıdır. Bu, tablonun düz bir taramasından ve birçok OR yan tümcesinden daha pahalı bir bellek olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.