计算distinct和Null值由聚合消除

时间:2009-05-12 07:55:08

标签: sql sql-server sql-server-2005 null aggregate

我正在使用SQL Server 2005.使用下面的查询(从我的真实查询中简化):

select a,count(distinct b),sum(a) from 
(select 1 a,1 b union all
select 2,2 union all
select 2,null union all
select 3,3 union all
select 3,null union all
select 3,null) a
group by a

有没有办法在不获取

的情况下进行计数

“警告:聚合或其他SET操作消除了空值。”

以下是我能想到的替代方案:

  1. 关闭ANSI_WARNINGS
  2. 分成两个查询,一个是count distinct,一个是where子句来消除空值,一个是总和:

    select t1.a, t1.countdistinctb, t2.suma from
    (
        select a,count(distinct b) countdistinctb from 
        (
            select 1 a,1 b union all
            select 2,2 union all
            select 2,null union all
            select 3,3 union all
            select 3,null union all
            select 3,null
        ) a
        where a.b is not null
        group by a
    ) t1
    left join
    (
        select a,sum(a) suma from 
        (
            select 1 a,1 b union all
            select 2,2 union all
            select 2,null union all
            select 3,3 union all
            select 3,null union all
            select 3,null
        ) a
        group by a
    ) t2 on t1.a=t2.a
    
  3. 忽略客户端中的警告

  4. 有更好的方法吗?我可能会沿着路线2走,但不喜欢代码重复。

4 个答案:

答案 0 :(得分:6)

select a,count(distinct isnull(b,-1))-sum(distinct case when b is null then 1 else 0 end),sum(a) from 
    (select 1 a,1 b union all
    select 2,2 union all
    select 2,null union all
    select 3,3 union all
    select 3,null union all
    select 3,null) a
    group by a

感谢Eoin,我找到了一种方法来做到这一点。您可以计算不同的值,包括空值,如果有任何使用不同的总和,则删除由于空值计数。

答案 1 :(得分:2)

任何可能返回null的地方,请使用

CASE WHEN Column IS NULL THEN -1 ELSE Column END AS Column

这将在查询期间将所有Null值分配为-1,并且它们将被计算/聚合,然后您可以在精细包装查询中执行相反的操作...

SELECT  
    CASE WHEN t1.a = -1 THEN NULL ELSE t1.a END as a
    , t1.countdistinctb
    , t2.suma

答案 2 :(得分:2)

这是一个迟到的注释,但正是这是谷歌的回归,我想提及它。

将NULL更改为另一个值是一个坏主意(tm)。

COUNT()正在这样做,而不是DISTINCT。

相反,在子查询中使用DISTINCT并返回一个数字,并在外部查询中聚合。

一个简单的例子是:

WITH A(A) AS (SELECT NULL UNION ALL SELECT NULL UNION ALL SELECT 1)
SELECT COUNT(*) FROM (SELECT DISTINCT A FROM A) B;

这允许使用COUNT(*),它不会忽略NULL(因为它计算记录,而不是值)。

答案 3 :(得分:1)

如果您不喜欢代码重复,那么为什么不使用公用表表达式?例如

WITH x(a, b) AS 
        (
                select 1 a,1 b union all
                select 2,2 union all
                select 2,null union all
                select 3,3 union all
                select 3,null union all
                select 3,null
        ) 
select t1.a, t1.countdistinctb, t2.suma from
(
        select a,count(distinct b) countdistinctb from 
        x a
        where a.b is not null
        group by a
) t1
left join
(
        select a,sum(a) suma from 
        x a
        group by a
) t2 on t1.a=t2.a