本文共 2098 字,大约阅读时间需要 6 分钟。
今天在做一个统计,其中有一个小小的需求在实现的时候小小的坑了一把
对于一个表,统计指定条件的数据有多少条,其中一个条件是经过cross apply计算出来的
那么,上一个小例子看看
declare @tb table(id int identity,dt date)declare @i intset @i=0-- 随机扔100个日期进临时表while @i<100 begin insert into @tb(dt) select dateadd(d,-rand()*2000,getdate()) select @i = @i + 1 endselect * from ( -- 获得最小日期 select min(dt) as start from @tb) across apply ( -- 根据最小日期获得当前自然年对应的开始日期 select (case when dateadd(year,datediff(year,start,getdate()),start)>convert(date,getdate()) then dateadd(year,datediff(year,start,getdate())-1,start) else dateadd(year,datediff(year,start,getdate()),start) end) as current_year_start) bcross apply ( -- 获得统计数据 select count(0) as cnt -- 获得所有日期中与当前日期差为偶数的数量 ,sum(case when datediff(d,dt,getdate())%2=0 then 1 else 0 end) as aa -- 获取当前自然年的日期数量,提示“在包含外部引用的被聚合表达式中指定了多个列。如果被聚合的表达式包含外部引用,那么该外部引用就必须是该表达式中所引用的唯一的一列。” ,sum(case when dt>b.current_year_start then 1 else 0 end) as cur from @tb) c
在这个例子里,我想统计符合当前自然年的数据时,报错了,在包含外部引用的被聚合表达式中指定了多个列。如果被聚合的表达式包含外部引用,那么该外部引用就必须是该表达式中所引用的唯一的一列。
尽管,我们还可以单独再附加一个cross apply,但总觉得这样不太方便
突然灵光一闪,我们可以对统计的内容也做个cross apply啊,把我们需要的数据直接扔到统计里,直接参与不就好了?
变形一下指令成为
declare @tb table(id int identity,dt date)declare @i intset @i=0-- 随机扔100个日期进临时表while @i<100 begin insert into @tb(dt) select dateadd(d,-rand()*2000,getdate()) select @i = @i + 1 endselect * from ( -- 获得最小日期 select min(dt) as start from @tb) across apply ( -- 获得统计数据 select count(0) as cnt -- 获得所有日期中与当前日期差为偶数的数量 ,sum(case when datediff(d,dt,getdate())%2=0 then 1 else 0 end) as aa -- 获取当前自然年的日期数量 ,sum(case when dt between current_year_start and getdate() then 1 else 0 end) as cur from @tb x cross apply ( -- 根据最小日期获得当前自然年对应的开始日期 select (case when dateadd(year,datediff(year,start,getdate()),start)>convert(date,getdate()) then dateadd(year,datediff(year,start,getdate())-1,start) else dateadd(year,datediff(year,start,getdate()),start) end) as current_year_start ) y) c
嗯,结果一切正常了,脑袋有坑啊,开始为什么就没这么想呢?
在这种统计的需求里,我们可以直接把其他需要参与计算的列一起扔到统计的cross apply里,这样就不会再有引用其他表数据的问题出现了
转载地址:http://nxvxi.baihongyu.com/