it-swarm-eu.dev

Otestujte, zda jsou sloupce NULL

Snažím se přijít na snadný dotaz, který mohu udělat, abych otestoval, zda má velká tabulka seznam položek, které mají ve sloupci ŽÁDNÝ sloupec alespoň jednu prázdnou (NULL/empty) hodnotu.

Potřebuji něco jako

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

Nechci to dělat

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

To by byl obrovský dotaz.

16
Dexter

Rozšíření odpovědi na @ db2 s méně (čtenými: nula) ručními wranglingy:

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;
16
Aaron Bertrand

Měli byste vyjmenovat všechny sloupce podle komentáře JNK.

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

Trochu méně efektivní přístup, který se tomu vyhýbá, je níže.

;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 

(Na základě této SO odpověď)

8
Martin Smith

Neexistuje žádná integrovaná syntaxe Nice, ale Management Studio má několik pohodlných funkcí pro rychlé vygenerování dotazu.

V Průzkumníku objektů rozbalte požadovanou tabulku, rozbalte ji a potom přetáhněte celou složku Sloupce do prázdného editoru dotazů. Tím se do dotazu přidá seznam sloupců oddělených čárkami.

Dále otevřete Najít a nahradit. Nastavte "Najít co" na , a nastavte „Nahradit“ na IS NULL OR (s mezerou) a stiskněte Replace All. Musíte poslední vyčistit sekvenci ručně.

Je to stále ošklivé, ale je to ošklivé méně náročné na práci.

5
db2

Vícenásobná řešení pro: null, všechna null, jeden a více sloupců plus to, aby bylo QUICK pomocí Top 1

Pokud potřebujete otestovat více sloupců, můžete použít následující:

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

První, otestujte NULL a spočítejte je:

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 

Výtěžek NULL:

Column_1  Column_2  Column_3
0         1         3

Pokud je výsledek 0, neexistují žádné NULL.

Second, počítejme non-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

... Ale protože zde počítáme jiné než NULL, lze to zjednodušit na:

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

Jeden výnos:

Column_1  Column_2  Column_3
3         2         0

Pokud je výsledek 0, sloupec je zcela tvořen NULL.

Konečně, pokud potřebujete pouze zkontrolovat konkrétní sloupec, pak TOP 1 je rychlejší, protože by se měl zastavit při prvním zásahu. Pak můžete volitelně použít count (*) k dosažení booleovského výsledku:

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 = Neexistují žádné NULL, 1 = Existuje alespoň jeden NULL

nebo

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 = Všichni jsou NULL, 1 = Existuje alespoň jeden non-NULL

Doufám, že to pomůže.

4
jwolf

UNPIVOT převádí sloupce do řádků. V tomto procesu eliminuje NULL hodnoty ( reference ).

Vzhledem k zadání

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);

dotaz 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;

bude produkovat výstup

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

Bohužel, řádek 4 byl zcela vyloučen, protože má pouze NULL! Lze jej pohodlně znovu zavést vložením fiktivní hodnoty do zdrojového dotazu:

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;

Agregací řádků na ID můžeme spočítat nenulové hodnoty. Porovnání s celkovým počtem sloupců ve zdrojové tabulce identifikuje řádky obsahující jeden nebo více 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;

Vypočítám 3 jako
počet sloupců ve zdrojové tabulce #t
+ 1 pro injektovanou figurínu
- 1 pro ID, které není NEPOUŽITÉ

Tuto hodnotu lze získat za běhu prozkoumáním katalogových tabulek.

Původní řádky lze získat spojením s výsledky.

Pokud mají být zkoumány jiné hodnoty než NULL, mohou být zahrnuty do klauzule where:

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

Diskuse

To vyžaduje identifikátor přenášený prostřednictvím UNPIVOT. Klíč by byl nejlepší. Pokud žádný neexistuje, může být injektována funkcí okna ROW_NUMBER () , i když to může být nákladné provedení.

Všechny sloupce musí být výslovně uvedeny uvnitř klauzule UNPIVOT. Lze je přetáhnout pomocí SSMS, jak navrhuje @ db2. Nebude to dynamické, když se budou chagny definice tabulky, jak by navrhoval Aaron Bertrand. To je však případ téměř všech SQL.

Pro můj poněkud omezený soubor dat je prováděcím plánem seskupený indexový index a agregovaný proud. To bude dražší z paměti než přímé skenování tabulky a spousta klauzur OR).

2
Michael Green