如何返回由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