计算不同值并通过聚合消除 Null 值
-
21-08-2019 - |
题
我正在使用 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 操作消除。”
以下是我能想到的替代方案:
- 关闭 ANSI_WARNINGS
分为两个查询,一个查询包含不同计数,一个 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
忽略客户端中的警告
有一个更好的方法吗?我可能会选择路线 2,但不喜欢代码重复。
解决方案
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,我找到了一种方法来做到这一点。您可以对包括空值在内的不同值进行计数,然后使用不同值之和删除由于空值而导致的计数(如果有)。
其他提示
任何可能返回 null 的地方,请使用
CASE WHEN Column IS NULL THEN -1 ELSE Column END AS Column
这将在查询期间将所有空值替换为 -1,并且它们将被如此计数/聚合,然后您可以在精细包装查询中执行相反的操作...
SELECT
CASE WHEN t1.a = -1 THEN NULL ELSE t1.a END as a
, t1.countdistinctb
, t2.suma
这是一个迟到的说明,但由于这是谷歌的回报,我想提一下。
将 NULL 更改为另一个值是一个坏主意。
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(因为它计算的是记录,而不是值)。
如果您不喜欢代码重复,那么为什么不使用公用表表达式呢?例如
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
不隶属于 StackOverflow