我有一个包含 processed_timestamp 列的表 - 如果已经处理了一条记录,那么该字段包含它被处理的日期时间,否则它为空。

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

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

这可能吗?

更新:表格非常大,因此效率非常重要。我可以运行两个查询来分别计算每个总数,但是如果我可以避免它,我想避免两次击中表。

有帮助吗?

解决方案

甲骨文:

按nvl2分组(字段,'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专家看一下之后,他同意:迄今为止没有提供的解决方案(包括这个解决方案)可以避免全表扫描(如果时间戳未被索引,则为表格,或者是索引)。它们都扫描表中的每个记录一次。

所有CASE / IF / NVL2()解决方案都为每一行执行空到字符串转换,从而在DBMS上引入了不必要的负载。这个解决方案没有这个问题。

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

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

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

斯图尔特

也许考虑这个解决方案。它(也是!)供应商非特定。

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

至于效率,这可以通过在一行中包含结果来避免2x索引搜索/表扫描/任何事情。如果你在结果中绝对需要2行,那么由于联合聚合,两次遍历集合可能是不可避免的。

希望这有帮助

另一种MySQL方法是使用 CASE 运算符,可以推广到 IF()之外的其他选择:

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

如果您的数据库对表有一个有效的COUNT(*)函数,您可以COUNT较小的数字,并减去。

SQL Server(从2012年开始):

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

我个人喜欢Pax的解决方案,但是如果你绝对只需要返回一行(就像我最近那样),那么在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

应该做这个工作。

如果列已编入索引,您最终可能会进行某种范围扫描并避免实际读取该表。

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 
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top