HAVING 子句仅在聚合分组不包含空值时过滤掉空行
HAVING clause to filter out null rows ONY if aggregate grouping contains not null values
我正在尝试从具有架构
的table创建汇总报告
PersonName varchar, IDNum int, CreateDate date
PersonName和CreateDate不为null,但是IDNum是可以为null的,这个table没有唯一约束,所以同一个PersonName可以有多个`IDNums,甚至多个null IDNums。
我想做的是创建一个按 CreateDate 分组的报告,如果该日期存在任何非空值,则忽略空 IDNums
因此,如果在 2 月 1 日存在 IDNum 为 20、21、23、NULL、NULL 的人,则报告在同一日期汇总 20、21、23 并忽略空值,如果另一个人在 2 月 1 日只存在 NULL IDNum,它们只显示一次 NULL。如果那个人在 2 月 2 日也作为 IDNums 25、30、NULL 存在,则他们在 2 月 1 日出现一次为 NULL,在 2 月 2 日再次出现为 25、30。 null 可以替换为其他一些默认值。不重要。
到目前为止我有
SELECT PersonName, COALESCE(IDNum, 0) IDNum, CreateDate FROM tbl
GROUP BY PersonName, COALESCE(IDNum, 0), CreateDate
HAVING COALESCE(IDNum, 0) >= CASE MAX(COALESCE(IDNum, 0)) WHEN 0 THEN 0 ELSE 1 END
这里的想法是,如果 IDNum 的计算结果为 0,如果另一个 IDNum 的计算结果大于 0,则不要在分组中对其进行计算,但这似乎不起作用。结果是相同的,就好像 having 子句不存在一样,我可以直观地看到同一 PersonName 的几个结果,其中包含同一日期的 0 和非零 IDNums。
检查此查询。只需删除重复的空值。然后数IDNum
。取决于显示你想要的结果
declare @t table (
PersonName varchar(10)
, IDNum int
, CreateDate date
)
insert into @t
values
('A', 20, '20180216')
,('A', 21, '20180216')
,('A', null, '20180216')
,('A', null, '20180216')
,('B', null, '20180216')
,('C', null, '20180216')
,('C', null, '20180216')
select
PersonName, IDNum, CreateDate
from (
select
*, cnt = count(*) over (partition by PersonName, CreateDate)
from
@t
group by PersonName, IDNum, CreateDate
) t
where
cnt = 1
or (cnt > 1 and IDNum is not null)
输出
PersonName, IDNum, CreateDate
-----------------------------
A 20 2018-02-16
A 21 2018-02-16
B NULL 2018-02-16
C NULL 2018-02-16
我正在尝试从具有架构
的table创建汇总报告PersonName varchar, IDNum int, CreateDate date
PersonName和CreateDate不为null,但是IDNum是可以为null的,这个table没有唯一约束,所以同一个PersonName可以有多个`IDNums,甚至多个null IDNums。
我想做的是创建一个按 CreateDate 分组的报告,如果该日期存在任何非空值,则忽略空 IDNums
因此,如果在 2 月 1 日存在 IDNum 为 20、21、23、NULL、NULL 的人,则报告在同一日期汇总 20、21、23 并忽略空值,如果另一个人在 2 月 1 日只存在 NULL IDNum,它们只显示一次 NULL。如果那个人在 2 月 2 日也作为 IDNums 25、30、NULL 存在,则他们在 2 月 1 日出现一次为 NULL,在 2 月 2 日再次出现为 25、30。 null 可以替换为其他一些默认值。不重要。
到目前为止我有
SELECT PersonName, COALESCE(IDNum, 0) IDNum, CreateDate FROM tbl
GROUP BY PersonName, COALESCE(IDNum, 0), CreateDate
HAVING COALESCE(IDNum, 0) >= CASE MAX(COALESCE(IDNum, 0)) WHEN 0 THEN 0 ELSE 1 END
这里的想法是,如果 IDNum 的计算结果为 0,如果另一个 IDNum 的计算结果大于 0,则不要在分组中对其进行计算,但这似乎不起作用。结果是相同的,就好像 having 子句不存在一样,我可以直观地看到同一 PersonName 的几个结果,其中包含同一日期的 0 和非零 IDNums。
检查此查询。只需删除重复的空值。然后数IDNum
。取决于显示你想要的结果
declare @t table (
PersonName varchar(10)
, IDNum int
, CreateDate date
)
insert into @t
values
('A', 20, '20180216')
,('A', 21, '20180216')
,('A', null, '20180216')
,('A', null, '20180216')
,('B', null, '20180216')
,('C', null, '20180216')
,('C', null, '20180216')
select
PersonName, IDNum, CreateDate
from (
select
*, cnt = count(*) over (partition by PersonName, CreateDate)
from
@t
group by PersonName, IDNum, CreateDate
) t
where
cnt = 1
or (cnt > 1 and IDNum is not null)
输出
PersonName, IDNum, CreateDate
-----------------------------
A 20 2018-02-16
A 21 2018-02-16
B NULL 2018-02-16
C NULL 2018-02-16