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

126 sql

我有一张桌子

create table us
(
 a number
);
Run Code Online (Sandbox Code Playgroud)

现在我有以下数据:

a
1
2
3
4
null
null
null
8
9
Run Code Online (Sandbox Code Playgroud)

现在我需要一个查询来计算列a中的null值不是null值

小智 215

这适用于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;
Run Code Online (Sandbox Code Playgroud)

要么:

select count(*) - count(a), count(a) from us;
Run Code Online (Sandbox Code Playgroud)

  • 首选`count(*)`到`count(1)` (4认同)
  • 使用“count(*)”和“count(a)”之间的区别也可以很好地与“group by”配合使用 (2认同)

Alb*_*gni 57

如果我理解正确,你想要计算列中的所有NULL和所有NOT NULL ...

如果这是正确的:

SELECT count(*) FROM us WHERE a IS NULL 
UNION ALL
SELECT count(*) FROM us WHERE a IS NOT NULL
Run Code Online (Sandbox Code Playgroud)

阅读评论后编辑完整查询:]


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;
Run Code Online (Sandbox Code Playgroud)

  • +1:到目前为止最简单,最快捷的方式.每个答案都没有,我感到震惊. (7认同)
  • 是但不是.我想他只想在一个查询中得到NULL而不是NULL ...你在两个查询中说如何做到这一点...... (6认同)

chr*_*eml 40

这是一个适用于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
Run Code Online (Sandbox Code Playgroud)

  • 类似的语法也适用于SQL Server.而且,这样做只会扫描一次表; UNION解决方案将进行两次表扫描.与小桌子无关,对于大桌子非常重要. (3认同)
  • 对于SQL Server唯一的更改是“空值”必须变为“空值”。单引号,而不是双引号。 (2认同)
  • 这在 Oracle 11g 中对我不起作用。@user155789 发布的版本为“case when a is null then 1 else 0 end”是有效的语法。 (2认同)

小智 22

正如我理解您的查询,您只需运行此脚本并获取Total Null,Total NotNull行,

select count(*) - count(a) as 'Null', count(a) as 'Not Null' from us;
Run Code Online (Sandbox Code Playgroud)


ell*_*087 15

通常我会用这个技巧

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
Run Code Online (Sandbox Code Playgroud)

  • 您需要交换“count_notnull”和“count_null”,现在它给出相反的结果:) (2认同)

Evi*_*ach 14

对于非空值

select count(a)
from us
Run Code Online (Sandbox Code Playgroud)

对于空值

select count(*)
from us

minus 

select count(a)
from us
Run Code Online (Sandbox Code Playgroud)

于是

SELECT COUNT(A) NOT_NULLS
FROM US

UNION

SELECT COUNT(*) - COUNT(A) NULLS
FROM US
Run Code Online (Sandbox Code Playgroud)

应该做的工作

  • 好的肉汁,男人,看看这些查询的执行计划.你正在开始左右桌面扫描,特别是那里有这样一个血腥的简单语句(从t中选择count(*),其中a为null`). (4认同)
  • 我没有数据库可供查看,但是该列是否已建立索引。如果是这样,则它是通过范围扫描发生的,否则,您将剩下全表扫描。在oracle中,NULL未存储在索引中,因此我怀疑您的示例并没有更好。您的里程可能会很高。 (2认同)

小智 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
Run Code Online (Sandbox Code Playgroud)

查询结果

如您在图像中看到的,第一个结果显示该表有16行。其中两行为NULL。因此,当我们使用Count(*)时,查询引擎将对行数进行计数,因此我们得到的计数结果为16。但是在Count(empid)的情况下,它会计算empid列中的非NULL值。所以我们得到的结果是14。

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

select COUNT(isnull(empid,1)) from @table1
Run Code Online (Sandbox Code Playgroud)

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

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


Abe*_*ker 6

为了提供另一种选择,Postgres 9.4+ 允许将a FILTER应用于聚合

SELECT
  COUNT(*) FILTER (WHERE a IS NULL) count_nulls,
  COUNT(*) FILTER (WHERE a IS NOT NULL) count_not_nulls
FROM us;
Run Code Online (Sandbox Code Playgroud)

SQLFiddle:http ://sqlfiddle.com/#!17/80a24/5


Rom*_*las -4

a 为空的元素数量:

select count(a) from us where a is null;
Run Code Online (Sandbox Code Playgroud)

a 不为 null 的元素数量:

select count(a) from us where a is not null;
Run Code Online (Sandbox Code Playgroud)