การนับค่า Null และค่าที่ไม่เป็น Null ในแบบสอบถามเดียว


141

ฉันมีโต๊ะ

create table us
(
 a number
);

ตอนนี้ฉันมีข้อมูลเช่น:

a
1
2
3
4
null
null
null
8
9

ตอนนี้ฉันต้องการเคียวรีเดียวเพื่อนับค่า null และไม่ใช่ค่า null ในคอลัมน์ a


3
สวัสดีคุณต้องนับรหัสฐานข้อมูลนี้ในฐานข้อมูลภาษาใดที่เรากำลังพูดถึง Best Regards, Iordan
IordanTanev

2
ฉันกำลังประหลาดใจไม่มีคำตอบเดียวที่มีสหภาพแรงงานที่เรียบง่ายของการนับเลือก (*) ...
Lieven Keersmaekers

1
@Lieven: ทำไมบนโลกนี้คุณจะใช้unionที่นี่? คำตอบของ Montecristo คือทางออกที่ดีที่สุด
Eric

1
เพราะ OP ต้องการด้วยแบบสอบถามเดียว คำตอบของ Montecristo แน่นอนคือไกลโดยทางออกที่ดีที่สุด ... เขาเพียงแค่ต้องการที่จะเพิ่มสหภาพ :)
Lieven Keersmaekers

1
และนั่นคือสิ่งที่ฉันได้รับจากการอ่านชื่อ จะแก้ไข
Eric

คำตอบ:


231

ใช้งานได้กับ Oracle และ SQL Server (คุณอาจสามารถใช้กับ RDBMS อื่นได้):

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

หรือ:

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

1
ใช้ความแตกต่างระหว่างcount(*)และcount(a)ยังทำงานได้ดีกับgroup by
แชนนอน

1
@shannon ฉันเห็นด้วยCOUNT(a)เป็นความคิดเห็นที่มีประโยชน์ในการเพิ่ม แต่สิ่งนี้จะส่งคำเตือน / ข้อผิดพลาดขึ้นอยู่กับสแต็คของคุณและอาจรับประกันความคิดเห็นในรหัส ฉันต้องการSUMวิธีการ
ริชาร์ด

4
ต้องการcount(*)ที่จะcount(1)
Lei Zhao

61

ถ้าฉันเข้าใจถูกต้องคุณต้องการนับ NULL ทั้งหมดและไม่เป็น NULL ทั้งหมดในคอลัมน์ ...

หากถูกต้อง:

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

แก้ไขแล้วเพื่อให้มีแบบสอบถามแบบเต็มหลังจากอ่านความคิดเห็น:]


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: ไกลโดยวิธีที่ง่ายที่สุดและเร็วที่สุด ฉันช็อคเมื่อทุกคำตอบไม่ใช่อย่างนี้
Eric

6
ใช่ แต่ไม่ใช่ ผมคิดว่าเขาต้องการที่จะมีจำนวนเป็นโมฆะและไม่ได้เป็นโมฆะในเพียงหนึ่งแบบสอบถาม ... คุณจะบอกว่าวิธีการทำที่อยู่ในแบบสอบถามที่สอง ...
Romain Linsolas

@romaintaz: ค่อนข้างถูกต้อง ฉันอ่านชื่อเรื่องเป็นคำถาม ในห้าการแก้ไขไม่มีใครคิดที่จะแก้ไข Yeesh
Eric

@romaintaz: ใช่คุณพูดถูกฉันถือเป็น "เรียกใช้ครั้งเดียวเพื่อค้นหาจำนวนโมฆะที่เรามี" ฉันไม่รู้ด้วยซ้ำว่าทำไม ^^ 'จะถูกต้องขอบคุณ
Alberto Zaccagni

1
@Montecristo: เพราะชื่อขอให้นับเฉพาะnull:)
เอริค

42

นี่คือรุ่นที่รวดเร็วและสกปรกที่ทำงานบน 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
ไวยากรณ์ที่คล้ายกันจะทำงานใน SQL Server เช่นกัน การทำแบบนี้จะสแกนตารางเพียงครั้งเดียวเท่านั้น โซลูชันของ UNION จะสแกนสองตาราง ไม่เกี่ยวข้องกับโต๊ะเล็ก ๆ สำคัญมากสำหรับโต๊ะใหญ่
Philip Kelley

2
เปลี่ยนแปลงเพียงอย่างเดียวสำหรับ SQL Server คือจะต้องกลายเป็น"Null values" 'Null values'คำพูดเดียวไม่คู่
Eric

1
SQLServer ใช้การสแกนดัชนีสำหรับแบบสอบถามนี้เทียบกับสองดัชนีพยายามใช้สหภาพ บนโต๊ะที่มี 40.000 แถวไม่มีความแตกต่างของความเร็ว
Lieven Keersmaekers

1
บนตารางที่มี 11.332.581 แถวมีการสแกนสองตารางไม่มีความแตกต่างของความเร็วที่น่าสังเกต (จริง ๆ แล้วการรวมกันเร็วกว่าเล็กน้อย )
Lieven Keersmaekers

1
สิ่งนี้ไม่ได้ผลสำหรับฉันใน Oracle 11g เวอร์ชัน @ user155789 โพสต์ด้วย "ตัวพิมพ์ใหญ่เมื่อ a เป็นโมฆะและอีก 1 จบ 0 จบ" เป็นไวยากรณ์ที่ใช้งานได้
Steve

25

ตามที่ฉันเข้าใจข้อความค้นหาของคุณคุณเพียงเรียกใช้สคริปต์นี้และรับผลรวม Null, ผลรวม NotNull ทั้งหมด,

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

23

สำหรับค่า Null

select count(a)
from us

สำหรับ nulls

select count(*)
from us

minus 

select count(a)
from us

ด้วยเหตุนี้

SELECT COUNT(A) NOT_NULLS
FROM US

UNION

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

ควรจะทำงาน

ดีกว่าที่ชื่อคอลัมน์ออกมาถูกต้อง

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

ในการทดสอบระบบของฉันมีค่าใช้จ่ายในการสแกนเต็มตาราง


4
น้ำเกรวี่ที่ดีคนดูแผนการดำเนินการสำหรับการค้นหาเหล่านี้ คุณกำลังถีบตารางสแกนไปทางซ้ายและขวาโดยเฉพาะอย่างยิ่งที่มีคำสั่งที่เรียบง่ายแบบนองเลือด ( select count(*) from t where a is null) ที่ทำสิ่งนี้
Eric

2
ฉันไม่มีฐานข้อมูลที่สะดวกในการค้นหา แต่คอลัมน์นั้นมีการจัดทำดัชนีหรือไม่ หากเป็นเช่นนั้นมันจะเกิดขึ้นผ่านการสแกนแบบช่วงไม่เช่นนั้นคุณจะเหลือการสแกนแบบเต็มตาราง ใน oracle NULL ไม่ได้ถูกจัดเก็บไว้ในดัชนีดังนั้นฉันสงสัยว่าตัวอย่างของคุณไม่ดีขึ้นมากนัก ระยะของคุณอาจมาก
EvilTeach

1
@EvilTeach: ดัชนีจะมีประโยชน์เฉพาะเมื่อคุณไม่ได้ดึงกลับ> ~ 10% ของแถว หลังจากนั้นจะทำการสแกนแบบเต็ม ในกรณีนี้คุณจะได้รับการสแกนอย่างน้อยหนึ่งครั้งหากไม่ใช่สองครั้ง
Eric

19

ฉันมักจะใช้เคล็ดลับนี้

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

นี่เป็นเรื่องยุ่งยากเล็กน้อย สมมติว่าตารางมีเพียงหนึ่งคอลัมน์จากนั้น Count (1) และ Count (*) จะให้ค่าต่างกัน

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

ผลลัพธ์การค้นหา

อย่างที่คุณเห็นในภาพผลลัพธ์แรกแสดงตารางมี 16 แถว แถวที่สองเป็น NULL ดังนั้นเมื่อเราใช้Count (*)เคียวรีเครื่องมือนับจำนวนแถวดังนั้นเราจึงได้ผลลัพธ์เป็น 16 แต่ในกรณีของCount (empid)มันจะนับค่าที่ไม่ใช่ค่า NULL ในคอลัมน์Empid EmpIDดังนั้นเราจึงได้ผลลัพธ์เป็น 14

ดังนั้นเมื่อใดก็ตามที่เราใช้ COUNT (คอลัมน์) ให้แน่ใจว่าเราดูแลค่า NULL ดังที่แสดงด้านล่าง

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

จะนับทั้งค่า NULL และไม่ใช่ NULL

หมายเหตุ : ใช้แบบเดียวกันแม้ว่าจะประกอบด้วยตารางมากกว่าหนึ่งคอลัมน์ จำนวน (1) จะให้จำนวนแถวทั้งหมดโดยไม่คำนึงถึงค่า NULL / Non-NULL เมื่อค่าของคอลัมน์ถูกนับโดยใช้การนับ (คอลัมน์) เราต้องดูแลค่า NULL


4

ฉันมีปัญหาที่คล้ายกัน: การนับค่าที่แตกต่างทั้งหมดนับค่า null เป็น 1 เช่นกัน การนับง่ายไม่สามารถใช้งานได้ในกรณีนี้เนื่องจากไม่ได้คำนึงถึงค่า Null

นี่เป็นตัวอย่างข้อมูลที่ทำงานกับ SQL และไม่เกี่ยวข้องกับการเลือกค่าใหม่ โดยทั่วไปเมื่อดำเนินการแตกต่างแล้วส่งคืนหมายเลขแถวในคอลัมน์ใหม่ (n) โดยใช้ฟังก์ชัน row_number () จากนั้นดำเนินการนับในคอลัมน์นั้น:

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

3

นี่คือสองวิธี:

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

หรือ

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


3

ลองนี้ ..

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

หากคุณใช้ 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;

ฉันไม่แนะนำให้คุณทำเช่นนี้ ... แต่ที่นี่คุณมีมัน (ในตารางเดียวกันเป็นผล)


2

ใช้ฟังก์ชัน ISNULL แบบฝัง



นี่เป็นคำตอบที่คู่ควร ฉันเองพบว่า COUNT (DISTINCT ISNULL (A, '')) ทำงานได้ดียิ่งขึ้นแล้ว COUNT (DISTINCT A) + ผลรวม (กรณีเมื่อ A เป็น 0 แล้ว 1 ELSE 0 END)
Vladislav

1

ถ้าเป็น mysql คุณสามารถลองแบบนี้

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

มันน่าเกลียด แต่มันจะส่งคืนเร็กคอร์ดเดียวที่มี 2 cols เพื่อระบุจำนวนของโมฆะและไม่เป็นโมฆะ


1

สิ่งนี้ใช้ได้ใน T-SQL หากคุณเพียงแค่นับจำนวนของบางสิ่งและคุณต้องการที่จะรวมโมฆะใช้ COALESCE แทนกรณี

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

ฉันได้เพิ่มการยกเลิก

 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 count(isnull(NullableColumn,-1))

2
ในขณะที่รหัสนี้อาจตอบคำถาม แต่มีบริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการที่รหัสนี้ตอบคำถามช่วยปรับปรุงมูลค่าระยะยาว
Vishal Chhodwani

1

คำตอบทั้งหมดนั้นผิดหรือล้าสมัยไปมาก

วิธีที่ง่ายและถูกต้องในการทำแบบสอบถามนี้คือการใช้COUNT_IFฟังก์ชั่น

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

0

ในกรณีที่คุณต้องการในบันทึกเดียว:

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

;-)


0

สำหรับการนับไม่ใช่ค่า Null

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

สำหรับการนับค่า Null

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

1
op ขอให้มีคำค้นหาเดียว :)
infografnet

0

ฉันสร้างตารางใน postgres 10 และทำงานได้ดังต่อไปนี้:

select count(*) from us

และ

select count(a is null) from us


a IS NULLผลิตTRUEหรือFALSEและ COUNT () จะนับค่า NOT NULL ทั้งหมด ดังนั้นcount(a is null)จะคืนค่าจำนวนแถวทั้งหมด
ypresto

0

ในกรณีของฉันฉันต้องการ " การแจกแจงโมฆะ " ในหลาย ๆ คอลัมน์:

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

ตาม '... ' มันสามารถขยายได้อย่างง่ายดายไปยังคอลัมน์อื่น ๆ ได้มากเท่าที่ต้องการ


-1

จำนวนขององค์ประกอบที่เป็นโมฆะ:

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

จำนวนองค์ประกอบที่ a ไม่เป็นโมฆะ:

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

1
คำถามนี้มีไว้สำหรับแบบสอบถามเดียว
DreamWave
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.