在单个查询中计算空值和非空值


141

我有桌子

create table us
(
 a number
);

现在我有类似的数据:

a
1
2
3
4
null
null
null
8
9

现在,我需要一个查询来计算a列中的空值非空值


3
嗨,您需要在哪种语言的数据库代码中使用哪种语言,我们在谈论哪种语言?最好的问候,Iordan
IordanTanev

2
令我惊讶的是,没有一个答案包含选择计数(*)的简单组合……
Lieven Keersmaekers,2009年

1
@Lieven:你到底为什么要在union这里使用?蒙特克里斯托的答案是迄今为止最好的解决方案。
埃里克

1
因为OP只需一个查询就可以了。Montecristo的答案确实是迄今为止最好的解决方案……他只需要添加工会即可:)
Lieven Keersmaekers 2009年

1
这就是我阅读标题所得到的。将进行编辑。
埃里克

Answers:


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
shannon 2015年

1
@shannon我同意,这COUNT(a)是添加的有用注释,但这确实会引发警告/错误,具体取决于您的堆栈,并可能需要在代码中添加注释。我更喜欢这种SUM方法。
理查德

4
宁愿count(*)count(1)
雷朝

61

如果我理解正确的话,您想在一列中计算所有NULL和所有NOT 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:到目前为止,最简单,最快的方法。如果不是每个答案,我都会感到震惊。
埃里克

6
是的,但是没有。我认为他希望仅在一个查询中具有NULL而不是NULL的数量...您是说如何在两个查询中做到这一点...
Romain Linsolas 09年

@romaintaz:完全正确。我读标题作为问题。在五次编辑中,没有人考虑修复它。esh
埃里克

@romaintaz:是的,您是对的,我将其视为“运行一次查询以发现我们有多少个空值”,我什至不知道为什么^^',要纠正,谢谢。
2009年

1
@Montecristo:因为标题只要求计数null:)
Eric

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解决方案将进行两次表扫描。与小桌子无关,对大桌子来说非常重要。
菲利普·凯利2009年

2
仅适用于SQL Server的改变是"Null values"必须成为'Null values'。单引号,而不是双引号。
埃里克

1
SQLServer使用此查询的索引扫描,而不是使用联合的两个索引查找。在具有40.000行的表上,没有速度差异。
Lieven Keersmaekers,2009年

1
在具有11.332.581行的表上,有两个表扫描,没有明显的速度差异(实际上,联合稍微快一点)。
Lieven Keersmaekers,2009年

1
在Oracle 11g中,这对我不起作用。@ user155789发布的版本带有“ case a为null然后1 else 0 end的情况”的语法。
2012年


23

非空

select count(a)
from us

为空

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)执行此操作的地方。
埃里克

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)的情况下,它会计算empid列中的非NULL值。所以我们得到的结果是14。

因此,每当使用COUNT(Column)时,请确保我们处理NULL值,如下所示。

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

将同时计数NULL和Non-NULL值。

注意:即使表由多个列组成,也是如此。Count(1)将给出总行数,而与NULL / Non-NULL值无关。仅当使用Count(Column)对列值进行计数时,我们才需要注意NULL值。


4

我有一个类似的问题:计算所有不同的值,将空值也计算为1。在这种情况下,简单的计数不起作用,因为它不考虑空值。

这是一个适用于SQL且不涉及选择新值的代码段。基本上,一旦执行了非重复操作,还可以使用row_number()函数在新列(n)中返回行号,然后对该列执行计数:

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)+ SUM(当A为NULL则为1 ELSE 0 END的情况)效果更好
弗拉迪斯拉夫

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个列的记录,指示空值与非空值的计数。


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

在Alberto的基础上,我添加了汇总。

 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

所有答案都是错误的或过时的。

执行此查询的简单正确方法是使用COUNT_IFfunction。

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

用于计算非空值

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

用于计数空值

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

1
该操作员询问单个查询:)
infografnet 16/09/13

0

我在postgres 10中创建了表格,以下两项均有效:

select count(*) from us

select count(a is null) from us


a IS NULL产生TRUEFALSE,并且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

a为空的元素数:

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

a不为null的元素数:

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

1
问题是一个查询。
DreamWave
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.