从一系列日期中获取日期间隔
Get an interval of dates from a range of dates
我有两个日期 2019 年 10 月 21 日和 2031 年 6 月 26 日,我需要从这两个日期开始的日期列表,从第一个日期开始间隔三个月,如下所示:
22/10/2019 | 21/01/2020
22/01/2020 | 21/04/2020
22/04/2020 | 21/07/2020
22/07/2020 | 21/10/2020
...
22/01/2031 | 21/04/2031
22/04/2031 | 26/06/2031
我试过使用 ROW_NUMBER()
和 DENSE_RANK()
以及 LAG()
来对两个日期之间的完整日期列表进行分组,但我似乎无法弄清楚。我想我可能需要以某种方式对其进行分区,但我无法正确处理。
如有不明白,请告诉我。我对此很陌生:)
您可以使用递归查询:
with cte (dt, end_dt) as (
select @start_dt, @end_dt
union all
select dateadd(month, 3, dt), end_dt from cte where dt < end_dt
)
select dt,
case when dateadd(month, 3, dt) < end_dt
then dateadd(day, -1, dateadd(month, 3, dt))
else end_dt
end as end_dt
from cte
order by dt;
如果您需要生成超过100个季度,您需要在查询的最后添加option (maxrecursion 0)
。
这也可以使用 'tally' 或基于数字的方法来完成。 tally_cte 的上限是 12^5=248,832(递归可以产生更多,可以根据需要增加)。
declare
@start_dt datetime='2019-10-21',
@end_dt datetime='2031-06-26'
;with
n(n) as (select * from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) v(n)),
tally_cte(n) as (
select row_number() over (order by (select null))
from n n1 cross join n n2 cross join n n3 cross join n n4 cross join n n5)
select t.*, cast(dt.dt as date) start_dt, cast(dateadd(MONTH, 3, dt.dt) as date) end_dt
from tally_cte t
cross apply (select dateadd(month, (n-1)*3, @start_dt) dt) dt
where n<datediff(month, @start_dt, @end_dt)/3;
N start_dt end_dt
1 2019-10-21 2020-01-21
2 2020-01-21 2020-04-21
3 2020-04-21 2020-07-21
...
45 2030-10-21 2031-01-21
我有两个日期 2019 年 10 月 21 日和 2031 年 6 月 26 日,我需要从这两个日期开始的日期列表,从第一个日期开始间隔三个月,如下所示:
22/10/2019 | 21/01/2020
22/01/2020 | 21/04/2020
22/04/2020 | 21/07/2020
22/07/2020 | 21/10/2020
...
22/01/2031 | 21/04/2031
22/04/2031 | 26/06/2031
我试过使用 ROW_NUMBER()
和 DENSE_RANK()
以及 LAG()
来对两个日期之间的完整日期列表进行分组,但我似乎无法弄清楚。我想我可能需要以某种方式对其进行分区,但我无法正确处理。
如有不明白,请告诉我。我对此很陌生:)
您可以使用递归查询:
with cte (dt, end_dt) as (
select @start_dt, @end_dt
union all
select dateadd(month, 3, dt), end_dt from cte where dt < end_dt
)
select dt,
case when dateadd(month, 3, dt) < end_dt
then dateadd(day, -1, dateadd(month, 3, dt))
else end_dt
end as end_dt
from cte
order by dt;
如果您需要生成超过100个季度,您需要在查询的最后添加option (maxrecursion 0)
。
这也可以使用 'tally' 或基于数字的方法来完成。 tally_cte 的上限是 12^5=248,832(递归可以产生更多,可以根据需要增加)。
declare
@start_dt datetime='2019-10-21',
@end_dt datetime='2031-06-26'
;with
n(n) as (select * from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) v(n)),
tally_cte(n) as (
select row_number() over (order by (select null))
from n n1 cross join n n2 cross join n n3 cross join n n4 cross join n n5)
select t.*, cast(dt.dt as date) start_dt, cast(dateadd(MONTH, 3, dt.dt) as date) end_dt
from tally_cte t
cross apply (select dateadd(month, (n-1)*3, @start_dt) dt) dt
where n<datediff(month, @start_dt, @end_dt)/3;
N start_dt end_dt
1 2019-10-21 2020-01-21
2 2020-01-21 2020-04-21
3 2020-04-21 2020-07-21
...
45 2030-10-21 2031-01-21