Zählen von Null- und Nicht-Null-Werten in einer einzelnen Abfrage

141

Ich habe einen Tisch

create table us
(
 a number
);

Jetzt habe ich Daten wie:

a
1
2
3
4
null
null
null
8
9

Jetzt brauche ich eine einzelne Abfrage, um null und nicht null Werte in Spalte a zu zählen

Eric
quelle
3
Hallo, wo brauchen Sie diese Art des Zählens von Datenbankcode in welcher Sprachdatenbank sprechen wir
? Mit
2
Ich bin überrascht, dass keine einzige Antwort eine einfache Vereinigung von Select Count (*) enthält ...
Lieven Keersmaekers
1
@Lieven: Warum um alles in der Welt würdest du unionhier ein verwenden? Montecristos Antwort ist bei weitem die beste Lösung.
Eric
1
Weil OP es mit einer einzigen Abfrage will. Montecristos Antwort ist in der Tat bei weitem die beste Lösung ... er muss nur die Gewerkschaft hinzufügen :)
Lieven Keersmaekers
1
Und das bekomme ich, wenn ich den Titel lese. Wird bearbeitet.
Eric

Antworten:

231

Dies funktioniert für Oracle und SQL Server (möglicherweise können Sie es auf einem anderen RDBMS zum Laufen bringen):

select sum(case when a is null then 1 else 0 end) count_nulls
     , count(a) count_not_nulls 
  from us;

Oder:

select count(*) - count(a), count(a) from us;
Rodrigue
quelle
1
Verwenden Sie die Unterscheidung zwischen count(*)und count(a)funktioniert auch gut mitgroup by
Shannon
1
@shannon Ich stimme zu, COUNT(a)ist ein nützlicher Kommentar zum Hinzufügen, aber dies wirft abhängig von Ihrem Stapel eine Warnung / einen Fehler auf und kann einen Kommentar im Code rechtfertigen. Ich würde die SUMMethode bevorzugen .
Richard
4
Bevorzugen count(*)zucount(1)
Lei Zhao
61

Wenn ich es richtig verstanden habe, möchten Sie alle NULL und alle NICHT NULL in einer Spalte zählen ...

Wenn das richtig ist:

SELECT count(*) FROM us WHERE a IS NULL 
UNION ALL
SELECT count(*) FROM us WHERE a IS NOT NULL

Nach dem Lesen der Kommentare bearbeitet, um die vollständige Abfrage zu erhalten:]


SELECT COUNT(*), 'null_tally' AS narrative 
  FROM us 
 WHERE a IS NULL 
UNION
SELECT COUNT(*), 'not_null_tally' AS narrative 
  FROM us 
 WHERE a IS NOT NULL;
Alberto Zaccagni
quelle
7
+1: Bei weitem der einfachste und schnellste Weg. Ich war schockiert, als nicht jede Antwort so war.
Eric
6
Ja aber nein. Ich denke, er möchte die Nummer NULL und nicht NULL in nur einer Abfrage haben ... Sie sagen, wie das in zwei Abfragen gemacht wird ...
Romain Linsolas
@ Romaintaz: Ganz richtig. Ich habe den Titel als Frage gelesen. In fünf Änderungen dachte niemand daran, das Problem zu beheben. Ja.
Eric
@romaintaz: Ja, Sie haben Recht, ich habe dies als "einmalige Abfrage ausführen, um festzustellen, wie viele Nullen wir haben", ich weiß nicht einmal warum ^^ ', korrigiert, danke.
Alberto Zaccagni
1
@Montecristo: Weil der Titel nur zählen wollte null:)
Eric
42

Hier ist eine schnelle und schmutzige Version, die unter Oracle funktioniert:

select sum(case a when null then 1 else 0) "Null values",
       sum(case a when null then 0 else 1) "Non-null values"
from us
christopheml
quelle
3
Eine ähnliche Syntax würde auch in SQL Server funktionieren. Wenn Sie dies auf diese Weise tun, wird die Tabelle nur einmal gescannt. Die UNION-Lösungen führen zwei Tabellenscans durch. Für kleine Tische irrelevant, für große sehr wichtig.
Philip Kelley
2
Nur eine Änderung für SQL Server "Null values"müsste werden 'Null values'. Einfache Anführungszeichen, keine doppelten.
Eric
1
SQLServer verwendet einen Index - Scan für diese Abfrage vs zwei Index sucht eine Vereinigung mit. Bei einer Tabelle mit 40.000 Zeilen gibt es keinen Geschwindigkeitsunterschied.
Lieven Keersmaekers
1
In einer Tabelle mit 11.332.581 Zeilen gibt es zwei Tabellenscans , bei denen kein Geschwindigkeitsunterschied erkennbar ist (tatsächlich ist die Vereinigung etwas schneller).
Lieven Keersmaekers
1
Dies hat bei mir in Oracle 11g nicht funktioniert. Die Version @ user155789 mit "case wenn a null ist, dann 1 else 0 end" war die Syntax, die funktionierte.
Steve
25

Wie ich Ihre Abfrage verstanden habe, führen Sie einfach dieses Skript aus und erhalten Total Null, Total NotNull Zeilen,

select count(*) - count(a) as 'Null', count(a) as 'Not Null' from us;
Ariful Haque
quelle
23

für Nicht-Nullen

select count(a)
from us

für Nullen

select count(*)
from us

minus 

select count(a)
from us

Daher

SELECT COUNT(A) NOT_NULLS
FROM US

UNION

SELECT COUNT(*) - COUNT(A) NULLS
FROM US

sollte den Job machen

Besser, dass die Spaltentitel korrekt herauskommen.

SELECT COUNT(A) NOT_NULL, COUNT(*) - COUNT(A) NULLS
FROM US

Bei einigen Tests auf meinem System kostet es einen vollständigen Tabellenscan.

EvilTeach
quelle
4
Gute Soße, Mann, sehen Sie sich die Ausführungspläne für diese Abfragen an. Sie starten Tischscans von links und rechts, besonders wenn es eine so verdammt einfache Aussage ( select count(*) from t where a is null) gibt, die dies tut.
Eric
2
Ich habe keine Datenbank zur Hand, aber entweder ist die Spalte indiziert oder nicht. Wenn dies der Fall ist, erfolgt dies über einen Entfernungsscan. Andernfalls bleibt Ihnen ein vollständiger Tabellenscan. In Oracle werden NULL-Werte nicht im Index gespeichert, daher vermute ich, dass Ihr Beispiel nicht viel besser ist. Ihre Laufleistung kann sehr.
EvilTeach
1
@EvilTeach: Indizes sind nur hilfreich, wenn Sie nicht> ~ 10% der Zeilen zurückziehen. Danach werden vollständige Scans gestartet. In diesem Fall erhalten Sie den Scan mindestens einmal, wenn nicht zweimal.
Eric
19

Normalerweise benutze ich diesen Trick

select sum(case when a is null then 0 else 1 end) as count_notnull,
       sum(case when a is null then 1 else 0 end) as count_null
from tab
group by a
elle0087
quelle
6

Das ist etwas knifflig. Angenommen, die Tabelle hat nur eine Spalte, dann ergeben Count (1) und Count (*) unterschiedliche Werte.

set nocount on
    declare @table1 table (empid int)
    insert @table1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(NULL),(11),(12),(NULL),(13),(14);

    select * from @table1
    select COUNT(1) as "COUNT(1)" from @table1
    select COUNT(empid) "Count(empid)" from @table1

Abfrageergebnisse

Wie Sie im Bild sehen können, zeigt das erste Ergebnis, dass die Tabelle 16 Zeilen enthält. von denen zwei Zeilen NULL sind. Wenn wir also Count (*) verwenden, zählt die Abfrage-Engine die Anzahl der Zeilen. Wir haben also das Count-Ergebnis als 16. Bei Count (empid) wurden jedoch die Nicht-NULL-Werte in der Spalte empid gezählt . Also haben wir das Ergebnis als 14 erhalten.

Wenn wir also COUNT (Spalte) verwenden, achten Sie darauf, dass die NULL-Werte wie unten gezeigt berücksichtigt werden.

select COUNT(isnull(empid,1)) from @table1

zählt sowohl NULL- als auch Nicht-NULL-Werte.

Hinweis : Dasselbe gilt auch dann, wenn die Tabelle aus mehr als einer Spalte besteht. Count (1) gibt die Gesamtzahl der Zeilen unabhängig von den NULL- / Nicht-NULL-Werten an. Nur wenn die Spaltenwerte mit Count (Column) gezählt werden, müssen wir uns um NULL-Werte kümmern.

Santhoshkumar LM
quelle
4

Ich hatte ein ähnliches Problem: alle unterschiedlichen Werte zu zählen und auch Nullwerte als 1 zu zählen. Eine einfache Zählung funktioniert in diesem Fall nicht, da Nullwerte nicht berücksichtigt werden.

Hier ist ein Snippet, das unter SQL funktioniert und keine Auswahl neuer Werte beinhaltet. Grundsätzlich geben Sie nach dem Ausführen der Unterscheidung auch die Zeilennummer in einer neuen Spalte (n) mit der Funktion row_number () zurück und führen Sie dann eine Zählung für diese Spalte durch:

SELECT COUNT(n)
FROM (
    SELECT *, row_number() OVER (ORDER BY [MyColumn] ASC) n
    FROM (
        SELECT DISTINCT [MyColumn]
                    FROM [MyTable]
        ) items  
) distinctItems
Starnuto di Topo
quelle
3

Hier sind zwei Lösungen:

Select count(columnname) as countofNotNulls, count(isnull(columnname,1))-count(columnname) AS Countofnulls from table name

ODER

Select count(columnname) as countofNotNulls, count(*)-count(columnname) AS Countofnulls from table name
Amal Hari
quelle
3

Versuchen

SELECT 
   SUM(ISNULL(a)) AS all_null,
   SUM(!ISNULL(a)) AS all_not_null
FROM us;

Einfach!

Rodrigo Prazim
quelle
3

Versuche dies..

SELECT CASE 
         WHEN a IS NULL THEN 'Null' 
         ELSE 'Not Null' 
       END a, 
       Count(1) 
FROM   us 
GROUP  BY CASE 
            WHEN a IS NULL THEN 'Null' 
            ELSE 'Not Null' 
          END 
Ayush Raj
quelle
2

Wenn Sie MS SQL Server verwenden ...

SELECT COUNT(0) AS 'Null_ColumnA_Records',
(
    SELECT COUNT(0)
    FROM your_table
    WHERE ColumnA IS NOT NULL
) AS 'NOT_Null_ColumnA_Records'
FROM your_table
WHERE ColumnA IS NULL;

Ich empfehle Ihnen nicht, dies zu tun ... aber hier haben Sie es (in derselben Tabelle wie das Ergebnis)

Andrei
quelle
2

Verwenden Sie die eingebettete ISNULL-Funktion.


Serget
quelle
Dies ist auch eine würdige Antwort. Ich persönlich fand, dass COUNT (DISTINCT ISNULL (A, '')) noch besser funktioniert als COUNT (DISTINCT A) + SUM (FALL, WENN A NULL IST, DANN 1 ELSE 0 END)
Vladislav
1

Wenn es MySQL ist, können Sie so etwas versuchen.

select 
   (select count(*) from TABLENAME WHERE a = 'null') as total_null, 
   (select count(*) from TABLENAME WHERE a != 'null') as total_not_null
FROM TABLENAME
TigerTiger
quelle
1
SELECT SUM(NULLs) AS 'NULLS', SUM(NOTNULLs) AS 'NOTNULLs' FROM 
    (select count(*) AS 'NULLs', 0 as 'NOTNULLs' FROM us WHERE a is null
    UNION select 0 as 'NULLs', count(*) AS 'NOTNULLs' FROM us WHERE a is not null) AS x

Es ist flüchtig, aber es wird ein einzelner Datensatz mit 2 Spalten zurückgegeben, der die Anzahl der Nullen gegenüber Nicht-Nullen angibt.

C-Pfund-Guru
quelle
1

Dies funktioniert in T-SQL. Wenn Sie nur die Anzahl von etwas zählen und die Nullen einschließen möchten, verwenden Sie COALESCE anstelle von Groß- und Kleinschreibung.

IF OBJECT_ID('tempdb..#us') IS NOT NULL
    DROP TABLE #us

CREATE TABLE #us
    (
    a INT NULL
    );

INSERT INTO #us VALUES (1),(2),(3),(4),(NULL),(NULL),(NULL),(8),(9)

SELECT * FROM #us

SELECT CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END AS 'NULL?',
        COUNT(CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END) AS 'Count'
    FROM #us
    GROUP BY CASE WHEN a IS NULL THEN 'NULL' ELSE 'NON-NULL' END

SELECT COALESCE(CAST(a AS NVARCHAR),'NULL') AS a,
        COUNT(COALESCE(CAST(a AS NVARCHAR),'NULL')) AS 'Count'
    FROM #us
    GROUP BY COALESCE(CAST(a AS NVARCHAR),'NULL')
DaveX
quelle
1

Aufbauend auf Alberto habe ich das Rollup hinzugefügt.

 SELECT [Narrative] = CASE 
 WHEN [Narrative] IS NULL THEN 'count_total' ELSE    [Narrative] END
,[Count]=SUM([Count]) FROM (SELECT COUNT(*) [Count], 'count_nulls' AS [Narrative]  
FROM [CrmDW].[CRM].[User]  
WHERE [EmployeeID] IS NULL 
UNION
SELECT COUNT(*), 'count_not_nulls ' AS narrative 
FROM [CrmDW].[CRM].[User] 
WHERE [EmployeeID] IS NOT NULL) S 
GROUP BY [Narrative] WITH CUBE;
Brian Connelly
quelle
1
SELECT
    ALL_VALUES
    ,COUNT(ALL_VALUES)
FROM(
        SELECT 
        NVL2(A,'NOT NULL','NULL') AS ALL_VALUES 
        ,NVL(A,0)
        FROM US
)
GROUP BY ALL_VALUES
Istiaque Hossain
quelle
1
select count(isnull(NullableColumn,-1))
Imran Shamszadeh
quelle
2
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Vishal Chhodwani
1

Alle Antworten sind entweder falsch oder extrem veraltet.

Die einfache und korrekte Art, diese Abfrage durchzuführen, ist die Verwendung der COUNT_IFFunktion.

SELECT
  COUNT_IF(a IS NULL) AS nulls,
  COUNT_IF(a IS NOT NULL) AS not_nulls
FROM
  us
Martín Fixman
quelle
0

Nur für den Fall, dass Sie es in einem einzigen Datensatz wollten:

select 
  (select count(*) from tbl where colName is null) Nulls,
  (select count(*) from tbl where colName is not null) NonNulls 

;-);

Sparhawk_
quelle
0

zum Zählen von nicht null Werten

select count(*) from us where a is not null;

zum Zählen von Nullwerten

 select count(*) from us where a is null;
Deep Shah
quelle
1
Die
Operation
0

Ich habe die Tabelle in Postgres 10 erstellt und beide der folgenden Funktionen haben funktioniert:

select count(*) from us

und

select count(a is null) from us

skrillybrick
quelle
a IS NULLerzeugt TRUEoder FALSE, und COUNT () zählt alle NOT NULL-Werte. Gibt also count(a is null)die Anzahl aller Zeilen zurück.
Ypresto
0

In meinem Fall wollte ich die " Nullverteilung " auf mehrere Spalten:

SELECT
       (CASE WHEN a IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS a_null,
       (CASE WHEN b IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS b_null,
       (CASE WHEN c IS NULL THEN 'NULL' ELSE 'NOT-NULL' END) AS c_null,
       ...
       count(*)
FROM us
GROUP BY 1, 2, 3,...
ORDER BY 1, 2, 3,...

Gemäß dem '...' kann es leicht auf mehr Spalten erweitert werden, so viele wie nötig

Vzzarr
quelle
-1

Anzahl der Elemente, bei denen a null ist:

select count(a) from us where a is null;

Anzahl der Elemente, bei denen a nicht null ist:

select count(a) from us where a is not null;
Romain Linsolas
quelle
1
Die Frage bezieht sich auf eine einzelne Abfrage.
DreamWave