第一次发布。在过去的6个月中学习了SQL,非常感谢您的帮助。我的数据结构如下:
DECLARE @tmp4 as TABLE (
AccountNumber int,
Date date,
DateRank int
)
INSERT INTO @tmp4
VALUES (001, '11/13/2018' , 1)
, (002, '12/19/2018', 2)
, (003, '1/23/2019' , 3)
, (004, '2/5/2019' , 4)
, (005, '3/10/2019' , 5)
, (006, '3/20/2019' , 6)
, (007, '4/8/2019' , 7)
, (008, '5/20/2019' , 8)
我需要使用此数据来计算滚动总数,一旦达到90天的阈值,该滚动总数将重置为0。我已经使用DateDiff函数计算连续日期之间的DateDiffs,并尝试使用LAG和其他窗口函数进行多种操作,但无法重置它。目标是找到只能每90天出现一次的“索引访问”。因此,我的计划是让一个字段在首次访问后读取0,并在下次访问90天后重置为0,以供下次访问,然后仅拉取访问值为0。
我尝试过的一种解决方案对于大多数集合都是正确的,但是没有为上述集合返回正确的值(第4行和第8行应从“索引访问”开始重新开始)。我期望此查询的结果为:
帐户日期DateRank滚动总计
001 | '11 / 13/2018'| 1 | 0
002 | '12 / 19/2018'| 2 | 35
003 |'1/23/2019'| 3 | 71
004 |'2/5/2019'| 4 | 84
005 |'3/10/2019'| 5 | 0(不是117)
006 |'3/20/2019'| 6 | 10
007 |'4/8/2019'| 7 | 29
008 |'5/20/2019'| 8 | 71感谢您的帮助。
这是我尝试的代码:
DECLARE @tmp2 as TABLE
(EmrNumber varchar(255)
, AdmitDateTime datetime
, DateRank int
, LagDateDiff int
, RunningTotal int
)
INSERT INTO @tmp2
SELECT tmp1.EmrNumber
, tmp1.AdmitDateTime
, tmp1.DateRank
--, LAG(tmp1.AdmitDateTime) OVER(PARTITION BY tmp1.EmrNumber ORDER BY tmp1.DateRank) as NextAdmitDate
, -DATEDIFF(DAY, tmp1.AdmitDateTime, LAG(tmp1.AdmitDateTime) OVER(PARTITION BY tmp1.EmrNumber ORDER BY tmp1.DateRank)) LagDateDiff
, IIF((SELECT SUM(sumt.total)
FROM (
SELECT -DATEDIFF(DAY, tmpsum.AdmitDateTime, LAG(tmpsum.AdmitDateTime) OVER(PARTITION BY tmpsum.EmrNumber ORDER BY tmpsum.DateRank)) total
FROM @tmp tmpsum
WHERE tmp1.EmrNumber = tmpsum.EmrNumber
AND tmpsum.AdmitDateTime <= tmp1.AdmitDateTime
) sumt) IS NULL, 0, (SELECT SUM(sumt.total)
FROM (
SELECT -DATEDIFF(DAY, tmpsum.AdmitDateTime, LAG(tmpsum.AdmitDateTime) OVER(PARTITION BY tmpsum.EmrNumber ORDER BY tmpsum.DateRank)) total
FROM @tmp tmpsum
WHERE tmp1.EmrNumber = tmpsum.EmrNumber
AND tmpsum.AdmitDateTime <= tmp1.AdmitDateTime
) sumt) ) as RunningTotal
FROM @tmp tmp1
SELECT *
, CASE WHEN LagDateDiff >90 THEN 0
WHEN RunningTotal = 0 THEN 0
ELSE LAG(LagDateDiff) OVER(PARTITION BY EmrNumber ORDER BY DateRank) + RunningTotal END AS RollingTotal
FROM @tmp2
您需要对此进行递归查询,因为必须逐行逐行检查运行总计:
with cte as (
select
Account,
Date,
DateRank,
0 RollingTotal
from @tmp4
where DateRank = 1
union all
select
t.Account,
t.Date,
t.DateRank,
case when RollingTotal + datediff(day, c.Date, t.Date) > 90
then 0
else RollingTotal + datediff(day, c.Date, t.Date)
end
from cte c
inner join @tmp4 t on t.DateRank = c.DateRank + 1
)
select * from cte
cte的锚点选择第一条记录(如DateRank
所示。然后,递归部分逐行处理行,并在超过90时重置运行计数。