Đếm các giá trị null và không null trong một truy vấn


141

Tôi có một cái bàn

create table us
(
 a number
);

Bây giờ tôi có dữ liệu như:

a
1
2
3
4
null
null
null
8
9

Bây giờ tôi cần một truy vấn duy nhất để đếm giá trị null không null trong cột a


3
Xin chào, bạn cần loại mã cơ sở dữ liệu này ở đâu trong cơ sở dữ liệu ngôn ngữ nào chúng ta đang nói về Trân trọng, Iordan
IordanTanev

2
Tôi ngạc nhiên không có câu trả lời duy nhất nào chứa một liên kết đơn giản gồm số lượng chọn (*) ...
Lieven Keersmaekers

1
@Lieven: Tại sao bạn lại sử dụng nó unionở đây? Câu trả lời của Montecristo là giải pháp tốt nhất.
Eric

1
Bởi vì OP muốn nó với một truy vấn duy nhất. Câu trả lời của Montecristo thực sự là giải pháp tốt nhất ... anh ta chỉ cần thêm liên minh :)
Lieven Keersmaekers

1
Và đó là những gì tôi nhận được khi đọc tiêu đề. Sẽ chỉnh sửa.
Eric

Câu trả lời:


231

Điều này hoạt động cho Oracle và SQL Server (bạn có thể làm cho nó hoạt động trên một RDBMS khác):

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

Hoặc là:

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

1
Sử dụng sự khác biệt giữa count(*)count(a)cũng hoạt động tốt vớigroup by
shannon

1
@shannon Tôi đồng ý, COUNT(a)là một nhận xét hữu ích để thêm, nhưng điều này không đưa ra cảnh báo / lỗi tùy thuộc vào ngăn xếp của bạn và có thể đảm bảo nhận xét trong mã. Tôi thích SUMphương pháp này.
Richard

4
Thích count(*)đếncount(1)
Lei Zhao

61

Nếu tôi hiểu chính xác, bạn muốn đếm tất cả NULL và tất cả KHÔNG NULL trong một cột ...

Nếu đó là chính xác:

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

Đã chỉnh sửa để có toàn bộ truy vấn, sau khi đọc các bình luận:]


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: Cho đến nay cách đơn giản nhất, nhanh nhất. Tôi đã bị sốc khi mọi câu trả lời không phải là điều này.
Eric

6
Đúng nhưng không phải thế. Tôi nghĩ rằng anh ta muốn có số lượng NULL chứ không phải NULL chỉ trong một truy vấn ... Bạn đang nói cách thực hiện điều đó trong hai truy vấn ...
Romain Linsolas

@romaintaz: Hoàn toàn đúng. Tôi đọc tiêu đề như câu hỏi. Trong năm lần chỉnh sửa, không ai nghĩ sẽ sửa nó. Diệp.
Eric

@romaintaz: Vâng, bạn đã đúng, tôi đã coi đây là "truy vấn một lần để phát hiện chúng tôi có bao nhiêu null", tôi thậm chí không biết tại sao ^^ ', sẽ sửa, cảm ơn.
Alberto Zaccagni

1
@Montecristo: Bởi vì tiêu đề chỉ yêu cầu đếm null:)
Eric

42

Đây là một phiên bản nhanh và bẩn hoạt động trên 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
Cú pháp tương tự cũng sẽ làm việc trong SQL Server. Ngoài ra, làm theo cách này sẽ chỉ quét bảng một lần; các giải pháp của UNION sẽ thực hiện quét hai bảng. Không liên quan cho các bàn nhỏ, rất quan trọng đối với những cái lớn.
Philip Kelley

2
Chỉ thay đổi cho SQL Server là "Null values"phải trở thành 'Null values'. Dấu ngoặc đơn, không nhân đôi.
Eric

1
SQLServer sử dụng quét chỉ mục cho truy vấn này so với hai chỉ mục tìm kiếm bằng cách sử dụng liên kết. Trên một bảng có 40.000 hàng, không có sự khác biệt về tốc độ.
Lieven Keersmaekers

1
Trên một bảng có 11.332.581 hàng, có hai lần quét bảng , không có sự khác biệt đáng chú ý về tốc độ (thực tế, liên kết nhanh hơn một chút ).
Lieven Keersmaekers

1
Điều này đã không làm việc cho tôi trong Oracle 11g. Phiên bản @ user155789 được đăng với "trường hợp khi a là null thì 1 khác 0 end" là cú pháp hoạt động.
Steve

25

Theo tôi hiểu truy vấn của bạn, Bạn chỉ cần chạy tập lệnh này và nhận các hàng Total Null, Total NotNull,

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

23

cho không null

select count(a)
from us

cho null

select count(*)
from us

minus 

select count(a)
from us

Vì thế

SELECT COUNT(A) NOT_NULLS
FROM US

UNION

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

phải làm công việc

Tốt hơn trong đó các tiêu đề cột đi ra chính xác.

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

Trong một số thử nghiệm trên hệ thống của tôi, nó có chi phí quét toàn bộ bảng.


4
Tốt, người đàn ông, nhìn vào kế hoạch thực hiện cho các truy vấn này. Bạn đang khởi động quét bàn bên trái và bên phải, đặc biệt là khi có một tuyên bố đơn giản đẫm máu ( select count(*) from t where a is null) thực hiện điều này.
Eric

2
Tôi không có cơ sở dữ liệu để tìm, nhưng cột có được lập chỉ mục hay không. Nếu đúng như vậy, nó xảy ra thông qua quét phạm vi, nếu không, bạn còn lại khá nhiều với quét toàn bộ bảng. Trong orory, NULL không được lưu trữ trong chỉ mục, vì vậy tôi nghi ngờ ví dụ của bạn không tốt hơn nhiều. Milage của bạn có thể rất.
EvilTeach

1
@EvilTeach: Chỉ mục chỉ hữu ích khi bạn không rút lại> ~ 10% số hàng. Sau đó, quét toàn bộ được bắt đầu. Trong trường hợp này, bạn sẽ được quét ít nhất một lần, nếu không hai lần.
Eric

19

thông thường tôi sử dụng thủ thuật này

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

Đây là một chút khó khăn. Giả sử bảng chỉ có một cột, thì Đếm (1) và Đếm (*) sẽ cho các giá trị khác nhau.

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

Kết quả truy vấn

Như bạn có thể thấy trong hình ảnh, Kết quả đầu tiên cho thấy bảng có 16 hàng. trong đó hai hàng là NULL. Vì vậy, khi chúng tôi sử dụng Count (*) , công cụ truy vấn sẽ đếm số lượng hàng, vì vậy chúng tôi có kết quả đếm là 16. Nhưng trong trường hợp Count (empid), nó đã đếm các giá trị không phải NULL trong empid cột . Vì vậy, chúng tôi đã nhận được kết quả là 14.

vì vậy bất cứ khi nào chúng tôi đang sử dụng COUNT (Cột), hãy đảm bảo chúng tôi chăm sóc các giá trị NULL như được hiển thị bên dưới.

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

sẽ tính cả hai giá trị NULL và Non-NULL.

Lưu ý : Điều tương tự được áp dụng ngay cả khi bảng được tạo thành từ nhiều hơn một cột. Đếm (1) sẽ cho tổng số hàng không phân biệt giá trị NULL / Non-NULL. Chỉ khi các giá trị cột được tính bằng Đếm (Cột), chúng ta mới cần quan tâm đến các giá trị NULL.


4

Tôi đã có một vấn đề tương tự: để đếm tất cả các giá trị riêng biệt, cũng tính các giá trị null là 1. Một số đơn giản không hoạt động trong trường hợp này, vì nó không tính đến giá trị null.

Đây là một đoạn hoạt động trên SQL và không liên quan đến việc lựa chọn các giá trị mới. Về cơ bản, một khi đã thực hiện phân biệt, cũng trả về số hàng trong một cột mới (n) bằng cách sử dụng hàm row_number (), sau đó thực hiện đếm trên cột đó:

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

3

Đây là hai giải pháp:

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

HOẶC LÀ

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

3

Thử

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

Đơn giản!


3

Thử cái này..

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

Nếu bạn đang sử dụng 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;

Tôi không khuyên bạn làm điều này ... nhưng ở đây bạn có nó (trong cùng một bảng với kết quả)


2

sử dụng chức năng nhúng ISNULL.



Đây cũng là một câu trả lời xứng đáng. Cá nhân tôi thấy rằng COUNT (DISTINCT ISNULL (A, '')) hoạt động thậm chí còn tốt hơn sau đó COUNT (DISTINCT A) + SUM (CASE KHI LÀ MỘT NULL THEN 1 ELSE 0 END)
Vladislav

1

Nếu mysql của nó, bạn có thể thử một cái gì đó như thế này.

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

Thật khó hiểu, nhưng nó sẽ trả về một bản ghi duy nhất với 2 cols cho biết số lượng null và không null.


1

Điều này hoạt động trong T-SQL. Nếu bạn chỉ đang đếm số lượng của một cái gì đó và bạn muốn bao gồm các giá trị null, hãy sử dụng COALESCE thay vì trường hợp.

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

Xây dựng thành phố của Alberto, tôi đã thêm phần giới thiệu.

 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
Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và / hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó.
Vishal Chhodwani

1

Tất cả các câu trả lời là sai hoặc cực kỳ lỗi thời.

Cách đơn giản và chính xác để thực hiện truy vấn này là sử dụng COUNT_IFhàm.

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

0

Chỉ trong trường hợp bạn muốn nó trong một bản ghi:

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

;-)


0

để đếm không giá trị null

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

để đếm giá trị null

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

1
Các op yêu cầu truy vấn duy nhất :)
infografnet

0

Tôi đã tạo bảng trong postgres 10 và cả hai cách sau đều hoạt động:

select count(*) from us

select count(a is null) from us


a IS NULLtạo TRUEhoặc FALSE, và COUNT () sẽ tính tất cả các giá trị KHÔNG NULL. Vì vậy, count(a is null)sẽ trả lại số lượng của tất cả các hàng.
ypresto

0

Trong trường hợp của tôi, tôi muốn " phân phối null " giữa nhiều cột:

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

Theo '...', nó có thể dễ dàng mở rộng ra nhiều cột hơn, bao nhiêu là cần thiết


-1

Số phần tử trong đó a là null:

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

Số phần tử trong đó a không null:

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

1
Câu hỏi dành cho một truy vấn duy nhất.
DreamWave 24/07/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.