68

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

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

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

那可能吗?

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

4

14 回答 14

53

在 MySQL 中,您可以执行类似的操作

SELECT 
    IF(ISNULL(processed_timestamp), 'NULL', 'NOT NULL') as myfield, 
    COUNT(*) 
FROM mytable 
GROUP BY myfield
于 2008-10-27T10:53:03.143 回答
45

在 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
于 2008-10-27T10:57:11.123 回答
28

甲骨文:

按 nvl2 分组(字段,'NOT NULL','NULL')

于 2008-10-27T10:56:10.313 回答
25

尝试以下操作,它与供应商无关:

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 上引入了不必要的负载。这个解决方案没有这个问题。

于 2008-10-27T10:54:19.910 回答
6

斯图尔特,

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

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

至于效率,这通过将结果包含在一行上来避免 2x 索引查找/表扫描/其他任何事情。如果您在结果中绝对需要 2 行,则由于联合聚合,两次通过集合可能是不可避免的。

希望这可以帮助

于 2008-10-27T13:20:12.423 回答
5

如果是甲骨文,那么你可以这样做:

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

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

于 2008-10-27T10:53:51.067 回答
3

另一种 MySQL 方法是使用CASEoperator,它可以推广到更多的替代方案IF()

SELECT CASE WHEN processed_timestamp IS NULL THEN 'NULL' 
            ELSE 'NOT NULL' END AS a,
       COUNT(*) AS n 
       FROM logs 
       GROUP BY a
于 2008-10-27T11:03:07.180 回答
2

SQL Server(从 2012 年开始):

SELECT IIF(ISDATE(processed_timestamp) = 0, 'NULL', 'NON NULL'), COUNT(*)
FROM MyTable
GROUP BY ISDATE(processed_timestamp);
于 2016-02-23T12:14:38.697 回答
2

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 
于 2016-03-03T05:46:35.773 回答
1

如果您的数据库对表具有有效的 COUNT(*) 函数,则可以 COUNT 中较小的数字,然后减去。

于 2008-10-28T02:49:34.880 回答
0

我个人喜欢 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

希望这可以帮助

于 2008-10-27T11:05:48.873 回答
0

[T-SQL]:

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

并且您可以在case 语句中添加您想要形成分区的任何其他值,例如今天、昨天、中午和下午2 点之间、星期四下午6 点之后。

于 2008-10-27T12:36:27.473 回答
0
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

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

于 2008-10-27T13:56:27.827 回答
0

在甲骨文中

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

应该做的工作。

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

于 2008-10-28T02:48:30.077 回答