如何返回由NULL和NOT NULL分组的logging?

我有一个表有一个processed_timestamp列 – 如果一个logging已被处理,那么该字段包含它处理的date时间,否则它是空的。

我想写一个返回两行的查询:

 NULL xx -- count of records with null timestamps NOT NULL yy -- count of records with non-null timestamps 

那可能吗?

更新:表格相当大,所以效率很重要。 我可以运行两个查询分别计算每个总数,但是如果可以避免的话,我想避免两次查询表。

甲骨文:

由nvl2组(field,'NOT NULL','NULL')

在MySQL中,你可以做类似的事情

 SELECT IF(ISNULL(processed_timestamp), 'NULL', 'NOT NULL') as myfield, COUNT(*) FROM mytable GROUP BY myfield 

在T-SQL(MS SQL Server)中,这是有效的:

 SELECT CASE WHEN Field IS NULL THEN 'NULL' ELSE 'NOT NULL' END FieldContent, COUNT(*) FieldCount FROM TheTable GROUP BY CASE WHEN Field IS NULL THEN 'NULL' ELSE 'NOT NULL' END 

尝试以下,这是供应商中立的:

 select 'null ' as type, count(*) as quant from tbl where tmstmp is null union all select 'not null' as type, count(*) as quant from tbl where tmstmp is not null 

在让我们的本地DB2专家看到这个之后,他同意:到目前为止(包括这个)所展示的解决scheme都不能避免全表扫描(如果时间戳没有索引,或者索引是其他的)。 他们全部扫描表中的每个logging一次。

所有CASE / IF / NVL2()解决scheme对每一行执行空string转换,在DBMS上引入不必要的负载。 这个解决scheme没有这个问题。

如果是oracle,那么你可以这样做:

 select decode(field,NULL,'NULL','NOT NULL'), count(*) from table group by decode(field,NULL,'NULL','NOT NULL'); 

我相信其他数据库也允许类似的技巧。

斯图尔特

也许考虑这个解决scheme 这也是(也!)供应商非特定的。

 SELECT count([processed_timestamp]) AS notnullrows, count(*) - count([processed_timestamp]) AS nullrows FROM table 

至于效率,这避免了2倍索引查找/表扫描/任何包括一行结果。 如果您在结果中绝对需要2行,则由于联合聚合,在该集合上可能不可避免地发生两遍。

希望这可以帮助

如果你的数据库有一个有效的COUNT(*)函数的表,你可以COUNT两者中较小的数字,然后减去。

另一个MySQL方法是使用CASE运算符 ,它可以推广到比IF()更多的select:

 SELECT CASE WHEN processed_timestamp IS NULL THEN 'NULL' ELSE 'NOT NULL' END AS a, COUNT(*) AS n FROM logs GROUP BY a 

我个人喜欢Pax的解决scheme,但如果你绝对只需要返回一行(就像我最近一样),在MS SQL Server 2005/2008中,你可以使用CTE“堆栈”这两个查询

 with NullRows (countOf) AS ( SELECT count(*) FORM table WHERE [processed_timestamp] IS NOT NULL ) SELECT count(*) AS nulls, countOf FROM table, NullRows WHERE [processed_timestamp] IS NULL GROUP BY countOf 

希望这可以帮助

[T-SQL]:

 select [case], count(*) tally from ( select case when [processed_timestamp] is null then 'null' else 'not null' end [case] from myTable ) a 

你可以在案例声明中添加任何你想要形成分区的其他值,例如,昨天中午至下午2点之间,星期四下午6点之后。

 Select Sum(Case When processed_timestamp IS NULL Then 1 Else 0 End) not_processed_count, Sum(Case When processed_timestamp Is Not NULL Then 1 Else 0 End) processed_count, Count(1) total From table 

编辑:没有仔细阅读,这一个返回一个单一的行。

在Oracle中

 SELECT COUNT(*), COUNT(TIME_STAMP_COLUMN) FROM TABLE; 

count(*)返回所有行的计数

count(column_name)返回不为NULL的行数,所以

 SELECT COUNT(*) - COUNT(TIME_STAMP_COLUMN) NUL_COUNT, COUNT(TIME_STAMP_COLUMN) NON_NUL_COUNT FROM TABLE 

应该做这个工作。

如果列被编入索引,最后可能会进行一些范围扫描,并避免实际读取表格。

SQL Server(从2012年开始):

 SELECT IIF(ISDATE(processed_timestamp) = 0, 'NULL', 'NON NULL'), COUNT(*) FROM MyTable GROUP BY ISDATE(processed_timestamp); 

另一种方式在T-sql(sql-server)

 select count(case when t.timestamps is null then 1 else null end) NULLROWS, count(case when t.timestamps is not null then 1 else null end) NOTNULLROWS from myTable t