it-swarm.com.de

Testen Sie, ob Spalten NULL sind

Ich versuche, eine einfache Abfrage zu finden, mit der ich testen kann, ob eine große Tabelle eine Liste von Einträgen enthält, die in EINER Spalte mindestens EINEN leeren Wert (NULL/leer) enthält.

Ich brauche so etwas

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

Ich will nicht müssen

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

Dies wäre eine riesige Abfrage.

16
Dexter

Eine Erweiterung der Antwort von @ db2 mit weniger (Lesen: Null) Hand-Wrangling:

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

Sie sollten alle Spalten gemäß dem Kommentar von JNK auflisten.

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

Ein etwas weniger effizienter Ansatz, der dies vermeidet, ist jedoch unten aufgeführt.

;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 

(Basierend auf dieser SO Antwort)

8
Martin Smith

Es gibt keine in Nice integrierte Syntax, aber Management Studio verfügt über einige praktische Funktionen, mit denen die Abfrage schnell generiert werden kann.

Führen Sie im Objekt-Explorer einen Drilldown zu der gewünschten Tabelle durch, erweitern Sie sie und ziehen Sie den gesamten Ordner "Spalten" in einen leeren Abfrageeditor. Dadurch wird der Abfrage eine durch Kommas getrennte Liste von Spalten hinzugefügt.

Öffnen Sie als Nächstes Suchen und Ersetzen. Setzen Sie "Find What" auf , und setze "Ersetzen durch" auf IS NULL OR (mit einem führenden Leerzeichen) und dann auf Alle ersetzen klicken. Sie müssen den letzten in der Sequenz von Hand bereinigen.

Es ist immer noch hässlich, aber es ist weniger arbeitsintensiv hässlich.

5
db2

Mehrere Lösungen für: einige Nullen, alle Nullen, einzelne und mehrere Spalten sowie SCHNELL mit Top 1

Wenn Sie mehrere Spalten testen müssen, können Sie Folgendes verwenden:

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

Testen Sie zuerst auf NULL und zählen Sie sie:

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 

Ergibt eine Anzahl von NULL:

Column_1  Column_2  Column_3
0         1         3

Wenn das Ergebnis 0 ist, gibt es keine NULL-Werte.

Zweitens zählen wir die Nicht-NULL-Werte:

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

... Aber da wir hier Nicht-NULL-Werte zählen, kann dies vereinfacht werden zu:

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

Beides ergibt:

Column_1  Column_2  Column_3
3         2         0

Wenn das Ergebnis 0 ist, besteht die Spalte vollständig aus NULL-Werten.

Schließlich , wenn Sie nur eine bestimmte Spalte überprüfen müssen, ist TOP 1 schneller, da es beim ersten Treffer aufhören sollte. Sie können dann optional count (*) verwenden, um ein boolesches Ergebnis zu erhalten:

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 = Es gibt keine NULL-Werte, 1 = Es gibt mindestens einen NULL-Wert

oder

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 = Sie sind alle NULL, 1 = Es gibt mindestens einen Nicht-NULL

Ich hoffe das hilft.

4
jwolf

UNPIVOT übersetzt Spalten in Zeilen. Dabei werden NULL-Werte ( Referenz ) eliminiert.

Angesichts der Eingabe

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

die UNPIVOT-Abfrage

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

wird die Ausgabe erzeugen

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

Leider wurde Zeile 4 vollständig eliminiert, da sie nur NULL-Werte enthält! Es kann bequem wieder eingeführt werden, indem ein Dummy-Wert in die Quellabfrage eingefügt wird:

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;

Durch Aggregieren der Zeilen auf ID können wir die Nicht-Null-Werte zählen. Ein Vergleich mit der Gesamtzahl der Spalten in der Quelltabelle identifiziert Zeilen, die eine oder mehrere NULL enthalten.

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;

Ich berechne 3 als
Anzahl der Spalten in der Quelltabelle #t
+ 1 für die injizierte Dummy-Säule
- 1 für ID, die nicht UNPIVOTED ist

Dieser Wert kann zur Laufzeit durch Untersuchen der Katalogtabellen ermittelt werden.

Die ursprünglichen Zeilen können durch Verbinden mit den Ergebnissen abgerufen werden.

Wenn andere Werte als NULL untersucht werden sollen, können sie in eine where-Klausel aufgenommen werden:

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

Diskussion

Dies erfordert eine Kennung, die über UNPIVOT übertragen wird. Ein Schlüssel wäre am besten. Wenn keine vorhanden ist, kann eine durch die Fensterfunktion ROW_NUMBER () injiziert werden, obwohl die Ausführung teuer sein kann.

Alle Spalten müssen explizit in der UNPIVOT-Klausel aufgeführt sein. Sie können mit SSMS hineingezogen werden, wie von @ db2 vorgeschlagen. Es wird nicht dynamisch sein, wenn die Tabellendefinition chagnes, wie Aaron Bertrands Vorschlag wäre. Dies ist jedoch bei fast allen SQL-Vorgängen der Fall.

Für meinen eher begrenzten Datensatz ist der Ausführungsplan ein Clustered-Index-Scan und ein Stream-Aggregat. Dies ist speicherintensiver als ein direkter Scan der Tabelle und viele OR -Klauseln).

2
Michael Green