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.