Zliczanie wartości null i niezerowych w jednym zapytaniu


141

Mam stolik

create table us
(
 a number
);

Teraz mam takie dane jak:

a
1
2
3
4
null
null
null
8
9

Teraz potrzebuję jednego zapytania, aby policzyć wartości null, a nie wartości null w kolumnie a


3
Cześć, gdzie potrzebujesz tego rodzaju liczenia kodu bazy danych w jakiej bazie językowej rozmawiamy Z poważaniem, Iordan
IordanTanev

2
Jestem zaskoczony żadna odpowiedź zawiera prosty unię select count (*) ...
Lieven Keersmaekers

1
@Lieven: Dlaczego, u licha, użyłbyś uniontutaj? Odpowiedź Montecristo jest zdecydowanie najlepszym rozwiązaniem.
Eric

1
Ponieważ OP chce tego za pomocą jednego zapytania. Odpowiedź Montecristo jest zdecydowanie najlepszym rozwiązaniem ... wystarczy dodać związek :)
Lieven Keersmaekers

1
I to właśnie dostaję za przeczytanie tytułu. Będzie edytować.
Eric

Odpowiedzi:


231

Działa to w przypadku Oracle i SQL Server (możesz mieć możliwość zmuszenia go do pracy na innym RDBMS):

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

Lub:

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

1
Używanie rozróżnienia między, count(*)a count(a)także działa dobrze zgroup by
shannon

1
@shannon Zgadzam się, COUNT(a)to przydatny komentarz do dodania, ale powoduje to ostrzeżenie / błąd w zależności od stosu i może uzasadniać komentarz w kodzie. Wolałbym tę SUMmetodę.
Richard

4
Wolę count(*), abycount(1)
Lei Zhao

61

Jeśli dobrze zrozumiałem, chcesz policzyć wszystkie NULL i wszystkie NIE NULL w kolumnie ...

Jeśli tak:

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

Edytowano pełne zapytanie, po przeczytaniu komentarzy:]


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: Zdecydowanie najprostszy i najszybszy sposób. Byłem zszokowany, gdy każda odpowiedź nie była taka.
Eric

6
Tak ale nie. Myślę, że chce mieć liczbę NULL, a nie NULL w jednym zapytaniu ... Mówisz, jak to zrobić w dwóch zapytaniach ...
Romain Linsolas

@romaintaz: Całkiem dobrze. Przeczytałem tytuł jako pytanie. W pięciu edycjach nikt nie pomyślał o naprawieniu tego. Yeesh.
Eric

@romaintaz: Tak, masz rację, potraktowałem to jako zapytanie „uruchom raz, aby zobaczyć, ile mamy null”, nawet nie wiem dlaczego ^^ ', poprawię, dzięki.
Alberto Zaccagni

1
@Montecristo: Ponieważ tytuł wymagał tylko liczenia null:)
Eric

42

Oto szybka i brudna wersja, która działa na 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
Podobna składnia działałaby również w SQL Server. Ponadto zrobienie tego w ten sposób spowoduje przeskanowanie tabeli tylko raz; rozwiązania UNION wykonają dwa skany tabeli. Nieistotne dla małych stolików, bardzo ważne dla dużych.
Philip Kelley

2
"Null values"Musiałaby nastąpić tylko zmiana dla SQL Server 'Null values'. Pojedyncze cudzysłowy, a nie podwójne.
Eric

1
SQLServer używa skanowania indeksu dla tego zapytania w porównaniu do dwóch wyszukiwań indeksów przy użyciu unii. Na stole z 40 000 rzędami nie ma różnicy prędkości.
Lieven Keersmaekers

1
Na tabeli z 11.332.581 wierszami są dwa skany tabeli , bez zauważalnej różnicy prędkości (w rzeczywistości połączenie jest nieco szybsze).
Lieven Keersmaekers

1
To nie zadziałało dla mnie w Oracle 11g. Wersja @ user155789 wysłana z "przypadek, gdy a jest null, a następnie 1 w przeciwnym razie 0 koniec" była składnią, która działała.
Steve

25

Jak zrozumiałem twoje zapytanie, po prostu uruchom ten skrypt i uzyskaj wiersze Total Null, Total NotNull,

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

23

dla wartości innych niż null

select count(a)
from us

dla wartości null

select count(*)
from us

minus 

select count(a)
from us

W związku z tym

SELECT COUNT(A) NOT_NULLS
FROM US

UNION

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

powinien wykonać swoją pracę

Lepiej pod tym względem, że tytuły kolumn są poprawne.

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

W przypadku niektórych testów w moim systemie kosztuje to pełne skanowanie tabeli.


4
Dobry sos, stary, spójrz na plany wykonania tych zapytań. Rozpoczynasz skanowanie tabeli w lewo i w prawo, szczególnie tam, gdzie jest takie cholernie proste stwierdzenie ( select count(*) from t where a is null), które to robi.
Eric

2
Nie mam pod ręką bazy danych, ale albo kolumna jest indeksowana, albo nie. Jeśli tak jest, dzieje się to poprzez skanowanie zakresu, w przeciwnym razie pozostaje prawie pełny skan tabeli. W wyroczni wartości NULL nie są przechowywane w indeksie, więc podejrzewam, że Twój przykład nie jest dużo lepszy. Twój przebieg może bardzo.
EvilTeach

1
@EvilTeach: indeksy są przydatne tylko wtedy, gdy nie wycofujesz> ~ 10% wierszy. Następnie inicjowane są pełne skanowanie. W takim przypadku otrzymasz skan co najmniej raz, jeśli nie dwa razy.
Eric

19

zwykle używam tej sztuczki

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

To trochę trudne. Załóżmy, że tabela ma tylko jedną kolumnę, wtedy Count (1) i Count (*) dadzą różne wartości.

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

Wyniki zapytania

Jak widać na obrazku, pierwszy wynik pokazuje, że tabela ma 16 wierszy. z czego dwa wiersze mają wartość NULL. Więc kiedy używamy Count (*), silnik zapytań liczy liczbę wierszy, więc otrzymaliśmy wynik zliczania jako 16. Ale w przypadku Count (empid) policzył wartości inne niż NULL w kolumnie empid . Otrzymaliśmy więc wynik 14.

więc ilekroć używamy COUNT (kolumna), upewnij się, że dbamy o wartości NULL, jak pokazano poniżej.

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

policzy wartości NULL i Non-NULL.

Uwaga : to samo dotyczy sytuacji, gdy tabela składa się z więcej niż jednej kolumny. Count (1) da całkowitą liczbę wierszy niezależnie od wartości NULL / Non-NULL. Dopiero gdy wartości kolumn są policzone przy użyciu Count (Column), musimy zadbać o wartości NULL.


4

Miałem podobny problem: policzyć wszystkie odrębne wartości, licząc również wartości zerowe jako 1. Prosta liczba nie działa w tym przypadku, ponieważ nie uwzględnia wartości null.

Oto fragment, który działa w języku SQL i nie obejmuje wyboru nowych wartości. Zasadniczo, po wykonaniu wyróżnienia, zwróć również numer wiersza w nowej kolumnie (n) za pomocą funkcji row_number (), a następnie wykonaj zliczanie w tej kolumnie:

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

3

Oto dwa rozwiązania:

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

LUB

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

3

Próbować

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

Prosty!


3

Spróbuj tego..

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

Jeśli używasz 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;

Nie polecam ci tego robić ... ale masz to (w tej samej tabeli co wynik)


2

użyj wbudowanej funkcji ISNULL.



To także godna odpowiedź. Osobiście odkryłem, że COUNT (DISTINCT ISNULL (A, '')) działa jeszcze lepiej niż COUNT (DISTINCT A) + SUM (CASE WHEN A IS NULL THEN 1 ELSE 0 END)
Vladislav

1

jeśli to mysql, możesz spróbować czegoś takiego.

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

Jest to niezłe, ale zwróci pojedynczy rekord z 2 kolumnami wskazującymi liczbę wartości null vs non null.


1

Działa to w T-SQL. Jeśli liczysz tylko liczbę i chcesz uwzględnić wartości null, użyj COALESCE zamiast wielkości liter.

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

Opierając się na Alberto, dodałem pakiet zbiorczy.

 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
Chociaż ten kod może odpowiedzieć na pytanie, zapewnia dodatkowy kontekst dotyczący tego, dlaczego i / lub jak ten kod odpowiada, poprawia jego długoterminową wartość.
Vishal Chhodwani

1

Wszystkie odpowiedzi są albo błędne, albo skrajnie nieaktualne.

Prostym i poprawnym sposobem wykonania tego zapytania jest użycie COUNT_IFfunkcji.

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

0

Na wypadek, gdybyś chciał to w jednym nagraniu:

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

;-)


0

do zliczania wartości innych niż null

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

do zliczania wartości null

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

1
Operator poprosił o pojedyncze zapytanie :)
infografnet

0

Stworzyłem tabelę w postgres 10 i oba poniższe działały:

select count(*) from us

i

select count(a is null) from us


a IS NULLprodukuje TRUEor FALSE, a COUNT () zliczy wszystkie wartości NIE NULL. Więc count(a is null)zwróci liczbę wszystkich wierszy.
ypresto

0

W moim przypadku chciałem „ dystrybucji zerowej ” między wieloma kolumnami:

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

Zgodnie z `` ... '' można go łatwo rozszerzyć na więcej kolumn, tyle, ile potrzeba


-1

Liczba elementów, w których a jest zerowe:

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

Liczba elementów, w których a nie jest zerowe:

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

1
Pytanie dotyczy pojedynczego zapytania.
DreamWave,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.