在 SQL 中累积日期
Cumulating dates in SQL
我有这个 table 和这个示例数据:
DECLARE @Sample TABLE (fill_date DATETIME, days_supplied INT)
INSERT INTO @Sample (fill_date, days_supplied)
VALUES (
'02/17/2005', --> DATEADD(dd, 500, '02/17/2005') = '07/02/2006'
500
),
(
'06/13/2005', --> DATEADD(dd, 30, '07/02/2006') = '08/01/2006'
30
),
(
'08/11/2005', --> DATEADD(dd, 30, '08/01/2006') = '08/31/2006'
30
)
我需要在第一行添加 days_supplied 到 fill_date,即 2006-07-02。如果结果高于下一行的 fill_date,我需要将下一行的 days_supplies 添加到上一行的 days_supplied 和 fill_date 的总和中。如果第一行的结果不高于下一行的 fill_date 那么我需要添加下一行的 days_supplied 和 fill_date,依此类推。
这是我最终需要的结果:
last_fill_date: '08/31/2006'.
实现此目标的最佳方法是什么?感谢任何帮助
对于这种类型的逻辑,您需要使用递归 CTE——唉:
with s as (
select s.*, row_number() over (order by fill_date) as seqnum
from sample s
),
cte as (
select fill_date, days_supplied, dateadd(day, days_supplied, fill_date) as end_date, seqnum
from s
where seqnum = 1
union all
select (case when s.fill_date > cte.end_date then s.fill_date else cte.end_date end),
s.days_supplied,
dateadd(day, s.days_supplied, (case when s.fill_date > cte.end_date then s.fill_date else cte.end_date end)),
s.seqnum
from cte join
s
on s.seqnum = cte.seqnum + 1
)
select max(end_date)
from cte;
Here 是一个 db<>fiddle.
请注意,这个问题有点含糊不清。我认为这些行是按 fill_date
排序的,这就是这个答案所假设的。
使用 window 函数
例子
Select *
,NewValue = DateAdd(DAY,sum(days_supplied) over (Order By Fill_date),min(fill_date) over())
From @Sample
Returns
fill_date days_supplied NewValue
2005-02-17 00:00:00.000 500 2006-07-02 00:00:00.000
2005-06-13 00:00:00.000 30 2006-08-01 00:00:00.000
2005-08-11 00:00:00.000 30 2006-08-31 00:00:00.000
EDIT - If you want just the final Record
Select Top 1
*
,NewValue = DateAdd(DAY,sum(days_supplied) over (Order By Fill_date),min(fill_date) over())
From @Sample
Order By NewValue desc
我有这个 table 和这个示例数据:
DECLARE @Sample TABLE (fill_date DATETIME, days_supplied INT)
INSERT INTO @Sample (fill_date, days_supplied)
VALUES (
'02/17/2005', --> DATEADD(dd, 500, '02/17/2005') = '07/02/2006'
500
),
(
'06/13/2005', --> DATEADD(dd, 30, '07/02/2006') = '08/01/2006'
30
),
(
'08/11/2005', --> DATEADD(dd, 30, '08/01/2006') = '08/31/2006'
30
)
我需要在第一行添加 days_supplied 到 fill_date,即 2006-07-02。如果结果高于下一行的 fill_date,我需要将下一行的 days_supplies 添加到上一行的 days_supplied 和 fill_date 的总和中。如果第一行的结果不高于下一行的 fill_date 那么我需要添加下一行的 days_supplied 和 fill_date,依此类推。
这是我最终需要的结果:
last_fill_date: '08/31/2006'.
实现此目标的最佳方法是什么?感谢任何帮助
对于这种类型的逻辑,您需要使用递归 CTE——唉:
with s as (
select s.*, row_number() over (order by fill_date) as seqnum
from sample s
),
cte as (
select fill_date, days_supplied, dateadd(day, days_supplied, fill_date) as end_date, seqnum
from s
where seqnum = 1
union all
select (case when s.fill_date > cte.end_date then s.fill_date else cte.end_date end),
s.days_supplied,
dateadd(day, s.days_supplied, (case when s.fill_date > cte.end_date then s.fill_date else cte.end_date end)),
s.seqnum
from cte join
s
on s.seqnum = cte.seqnum + 1
)
select max(end_date)
from cte;
Here 是一个 db<>fiddle.
请注意,这个问题有点含糊不清。我认为这些行是按 fill_date
排序的,这就是这个答案所假设的。
使用 window 函数
例子
Select *
,NewValue = DateAdd(DAY,sum(days_supplied) over (Order By Fill_date),min(fill_date) over())
From @Sample
Returns
fill_date days_supplied NewValue
2005-02-17 00:00:00.000 500 2006-07-02 00:00:00.000
2005-06-13 00:00:00.000 30 2006-08-01 00:00:00.000
2005-08-11 00:00:00.000 30 2006-08-31 00:00:00.000
EDIT - If you want just the final Record
Select Top 1
*
,NewValue = DateAdd(DAY,sum(days_supplied) over (Order By Fill_date),min(fill_date) over())
From @Sample
Order By NewValue desc