Conteggio dei valori null e non null in una singola query


141

Ho un tavolo

create table us
(
 a number
);

Ora ho dati come:

a
1
2
3
4
null
null
null
8
9

Ora ho bisogno di una singola query per contare i valori null e non null nella colonna a


3
Ciao, dove hai bisogno di questo tipo di conteggio del codice del database in quale database di lingua stiamo parlando. I migliori saluti, Iordan
IordanTanev

2
Sono sorpreso che nessuna risposta singola contenga una semplice unione di numero selezionato (*) ...
Lieven Keersmaekers,

1
@Lieven: Perché mai dovresti usare un unionqui? La risposta di Montecristo è di gran lunga la soluzione migliore.
Eric,

1
Perché OP lo vuole con una singola query. La risposta di Montecristo è di gran lunga la soluzione migliore ... deve solo aggiungere il sindacato :)
Lieven Keersmaekers

1
Ed è quello che ottengo leggendo il titolo. Modifica.
Eric,

Risposte:


231

Funziona con Oracle e SQL Server (potresti riuscire a farlo funzionare su un altro RDBMS):

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

O:

select count(*) - count(a), count(a) from us;

1
Usando la distinzione tra count(*)e count(a)funziona anche bene congroup by
shannon

1
@shannon Sono d'accordo, COUNT(a)è un commento utile da aggiungere, ma questo genera un avvertimento / errore a seconda del tuo stack e potrebbe giustificare un commento in codice. Preferirei il SUMmetodo.
Richard,

4
Preferisco count(*)acount(1)
Lei Zhao

61

Se ho capito bene vuoi contare tutto NULL e tutto NOT NULL in una colonna ...

Se è corretto:

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

Modificato per avere la query completa, dopo aver letto i commenti:]


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;

7
+1: di gran lunga il modo più semplice e veloce. Ero scioccato quando ogni risposta non era questa.
Eric,

6
Sì ma no Penso che voglia avere il numero di NULL e non NULL in una sola query ... Stai dicendo come farlo in due query ...
Romain Linsolas

@romaintaz: Esatto. Ho letto il titolo come una domanda. In cinque modifiche, nessuno ha pensato di risolverlo. Yeesh.
Eric,

@romaintaz: Sì, hai ragione, l'ho preso come "Esegui una volta sola query per individuare quanti null abbiamo", non so nemmeno perché ^^ ', andando a correggere, grazie.
Alberto Zaccagni,

1
@Montecristo: Perché il titolo richiedeva solo il conteggio null:)
Eric

42

Ecco una versione rapida e sporca che funziona su Oracle:

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

3
Sintassi simile funzionerebbe anche in SQL Server. Inoltre, in questo modo verrà eseguita la scansione della tabella una sola volta; le soluzioni UNION eseguiranno due scansioni di tabelle. Irrilevante per i tavolini, molto importante per quelli enormi.
Philip Kelley,

2
Dovrebbe "Null values"diventare solo la modifica per SQL Server 'Null values'. Virgolette singole, non doppie.
Eric,

1
SQLServer utilizza una scansione dell'indice per questa query rispetto a due ricerche di indice utilizzando un'unione. Su una tabella con 40.000 righe, non c'è differenza di velocità.
Lieven Keersmaekers,

1
Su una tabella con 11.332.581 righe, ci sono due scansioni della tabella , nessuna differenza di velocità evidente (in realtà, l'unione è leggermente più veloce).
Lieven Keersmaekers,

1
Questo non ha funzionato per me in Oracle 11g. La versione @ user155789 pubblicata con "case when a is null then 1 else 0 end" era la sintassi che funzionava.
Steve,

25

Come ho capito la tua domanda, devi solo eseguire questo script e ottenere le righe Total Null, Total NotNull,

select count(*) - count(a) as 'Null', count(a) as 'Not Null' from us;

23

per non null

select count(a)
from us

per null

select count(*)
from us

minus 

select count(a)
from us

Quindi

SELECT COUNT(A) NOT_NULLS
FROM US

UNION

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

dovrebbe fare il lavoro

Meglio che i titoli delle colonne risultino corretti.

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

In alcuni test sul mio sistema, costa una scansione completa della tabella.


4
Buon sugo, amico, guarda i piani di esecuzione di queste domande. Stai dando il via alle scansioni del tavolo a sinistra ea destra, specialmente dove c'è una dichiarazione così maledettamente semplice ( select count(*) from t where a is null) che lo fa.
Eric,

2
Non ho un database a portata di mano, ma la colonna è indicizzata o meno. Se lo è, accade tramite una scansione di intervallo, altrimenti, ti rimane praticamente con una scansione completa della tabella. In Oracle, i NULL non vengono archiviati nell'indice, quindi sospetto che l'esempio non sia molto migliore. La tua distanza potrebbe essere molto.
EvilTeach

1
@EvilTeach: gli indici sono utili solo quando non stai tirando indietro> ~ 10% delle righe. Successivamente, vengono avviate le scansioni complete. In questo caso, otterrai la scansione almeno una volta, se non due volte.
Eric,

19

di solito uso questo trucco

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


6

Questo è un po 'complicato. Supponiamo che la tabella abbia solo una colonna, quindi Count (1) e Count (*) forniranno valori diversi.

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

Risultati della query

Come puoi vedere nell'immagine, il primo risultato mostra che la tabella ha 16 righe. di cui due righe sono NULL. Quindi quando usiamo Count (*) il motore di query conta il numero di righe, quindi abbiamo ottenuto il risultato del conteggio come 16. Ma in caso di Count (empid) ha contato i valori non NULL nella colonna empid . Quindi abbiamo ottenuto il risultato come 14.

quindi ogni volta che utilizziamo COUNT (colonna) assicurati di occuparci dei valori NULL come mostrato di seguito.

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

conterà sia i valori NULL che Non-NULL.

Nota : la stessa cosa vale anche quando la tabella è composta da più di una colonna. Count (1) fornirà il numero totale di righe indipendentemente dai valori NULL / Non-NULL. Solo quando i valori delle colonne vengono contati utilizzando Count (Column), dobbiamo occuparci dei valori NULL.


4

Ho avuto un problema simile: contare tutti i valori distinti, contando anche i valori null come 1. Un semplice conteggio non funziona in questo caso, in quanto non tiene conto di valori nulli.

Ecco uno snippet che funziona su SQL e non comporta la selezione di nuovi valori. Fondamentalmente, una volta eseguito il distinto, restituisce anche il numero di riga in una nuova colonna (n) utilizzando la funzione row_number (), quindi esegui un conteggio su quella colonna:

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

3

Ecco due soluzioni:

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

O

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

3

Provare

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

Semplice!


3

Prova questo..

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 

2

Se stai utilizzando MS Sql Server ...

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;

Non ti consiglio di farlo ... ma qui ce l'hai (nella stessa tabella del risultato)


2

usa la funzione ISNULL integrata.



Questa è anche una risposta degna. Personalmente ho scoperto che COUNT (DISTINCT ISNULL (A, '')) funziona ancora meglio di COUNT (DISTINCT A) + SUM (CASO QUANDO A È NULL ENEN 1 ENSE 0 END)
Vladislav

1

se è mysql, puoi provare qualcosa del genere.

select 
   (select count(*) from TABLENAME WHERE a = 'null') as total_null, 
   (select count(*) from TABLENAME WHERE a != 'null') as total_not_null
FROM TABLENAME

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

È fugly, ma restituirà un singolo record con 2 cols che indicano il conteggio di null vs non null.


1

Funziona in T-SQL. Se stai solo contando il numero di qualcosa e vuoi includere i valori null, usa COALESCE anziché case.

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

1

Partendo da Alberto, ho aggiunto il rollup.

 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;

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

1
select count(isnull(NullableColumn,-1))

2
Mentre questo codice può rispondere alla domanda, fornendo un contesto aggiuntivo riguardo al perché e / o al modo in cui questo codice risponde alla domanda migliora il suo valore a lungo termine.
Vishal Chhodwani,

1

Tutte le risposte sono errate o estremamente obsolete.

Il modo semplice e corretto di eseguire questa query è utilizzare la COUNT_IFfunzione.

SELECT
  COUNT_IF(a IS NULL) AS nulls,
  COUNT_IF(a IS NOT NULL) AS not_nulls
FROM
  us

0

Nel caso in cui lo volessi in un singolo record:

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

;-)


0

per il conteggio di valori non nulli

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

per contare valori nulli

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

1
L'operazione ha richiesto una singola query :)
infografnet,

0

Ho creato la tabella in Postgres 10 ed entrambi i seguenti hanno funzionato:

select count(*) from us

e

select count(a is null) from us


a IS NULLproduce TRUEo FALSEe COUNT () conterà tutti i valori NOT NULL. Quindi count(a is null)restituirà il conteggio di tutte le righe.
ypresto

0

Nel mio caso volevo la " distribuzione nulla " tra più colonne:

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,...

Come da '...' è facilmente estendibile a più colonne, quante ne servono


-1

Numero di elementi in cui a è null:

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

Numero di elementi in cui a non è nullo:

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

1
La domanda è per una singola query.
DreamWave,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.