我把头发拉过来这么简单......
我正在记录会员参加健身俱乐部的天数。默认情况下,我假设会员每天都会参加。当他们生病时,我会记录表中没有的日期和总天数(即DateFrom
,DateEnd
,TotalDays
)。缺席的总天数是DateFrom
和DateEnd
之间的差异。
现在有时候我不知道会员何时回到健身房。只是他们已经停止参加某一天。因此,DateEnd
和TotalDays
未知。因此,总天数是通过取DateFrom
和今天的日期之间的差异来计算的。
Table: InactiveOnProgram
Columns: PersonId, DateFrom, DateEnd, TotalDays
数据:
1,01/01/2012,05/01/2012,5
1,05/01/2012,08/01/2012,3
2,01/02/2012,05/02/2012,5
2,05/02/2012,08/02/2012,3
2,20/02/2012,null,null
我的以下查询适用于personId = 2。没有的总天数是8 + 2 = 10天(2天是20/02/2012至22/02/2012 =今天)。但是对于personId = 1,它返回null,而不是8天!
SQL:
(SELECT
case ( isnull(sum(TotalDays), 0) )
when 0 then 0
else CAST(SUM(TotalDays) as DECIMAL(20,2))
end
FROM InactiveOnProgram
)
+
(SELECT
case ( isnull( DateFrom, 0) )
when null then 0
when 0 then 0
else CAST(datediff(day,DateFrom, getdate()) as DECIMAL(20,2))
end
FROM InactiveOnProgram
WHERE (TotalDays is null or TotalDays =0)
AND DateTo is null
)
知道我在这里缺少什么吗?!据我所知,sql的第二部分返回null,因此忽略了第一部分!
非常感谢任何帮助。
由于
答案 0 :(得分:2)
您可以将其编写为单个查询:
declare @InactiveOnProgram table
(PersonId int, DateFrom datetime, DateEnd datetime, TotalDays int)
insert into @InactiveOnProgram (PersonId , DateFrom , DateEnd , TotalDays)
select 1,'20120101','20120105',5 union all
select 1,'20120105','20120108',3 union all
select 2,'20120201','20120205',5 union all
select 2,'20120205','20120208',3 union all
select 2,'20120220',null,null
select PersonId,SUM(COALESCE(TotalDays,DATEDIFF(day,DateFrom,CURRENT_TIMESTAMP)))
from @InactiveOnProgram group by PersonId
我对存储TotalDays并不满意,但鉴于您的数据集,似乎有必要,因为显然,从1日 - 5日= 5天,但是从5日 - 8日= 3天。
答案 1 :(得分:1)
您是否只猜测第二部分返回null或者您知道吗?因为据我所知,第一部分是返回未定义的东西。
您需要以不同的顺序使用SUM()和ISNULL(),例如:
select cast(sum(isnull(TotalDays, 0)) as decimal(20,2)) as totdays
在第二种情况下,您可以使用下一个:
datediff(day, isnull(DateFrom, getdate()), getdate())
这样您就可以在计算/转换之前消除空值。
答案 2 :(得分:0)
问题基本上是在SQL中,计算中的null
项导致null
。
确保结果中无法null
。
答案 3 :(得分:0)
也许这是你的解决方案:
select personid, sum( closed + unclosed)
from (
SELECT personid
, CAST(SUM(isnull(nullif(TotalDays,0),0)) as DECIMAL(20,2)) as closed
, case when min(isnull(nullif(DateFrom,0),0))=0 OR (SUM(isnull(nullif(TotalDays,0),0)) >0 AND min(isnull(nullif(dateend,0),0)) >0) then 0 else min(CAST(datediff(day,DateFrom, getdate()) as DECIMAL(20,2))) end as unclosed
FROM test
group by personid
--WITH ROLLUP
) as test
group by personid
WITH ROLLUP