sql - 将日期范围从单行拆分为多行显示的月份
问题描述
我有一个包含几百万个条目的表,所以我需要一个可以在一堆不同场景下工作的解决方案,因为我发现的大多数解决方案最多只能用于几次迭代。
我有一个 PERIOD_FROM 和一个 PERIOD_TO 状态检查,也就是帐户处于这种状态的时间。分开两个月的差额是没有问题的,但相当多的条目是用于预付款的帐户,因此它们的状态最多不会改变 2 年。
简化后的原始表格如下所示:
ID PERIOD_FROM PERIOD_TO DAYS
---------------------------------------------------------
115052454 02/04/2019 01/04/2021 730
115678935 06/04/2021 05/04/2023 729
119040627 06/04/2021 05/04/2023 729
115005487 01/04/2019 29/03/2021 728
116414279 17/04/2019 09/04/2021 723
116411046 17/04/2019 04/04/2021 718
116693271 24/04/2019 04/04/2021 711
123935704 05/07/2019 29/05/2021 694
119040627 16/05/2019 05/04/2021 690
115976183 02/05/2019 01/03/2021 669
我为两个月的差异解决方案所做的是创建一个 concat,如下所示:
CASE WHEN CONCAT(DATEPART(YYYY, [PERIOD_FROM]), FORMAT([PERIOD_FROM], 'MM')) = CONCAT(DATEPART(YYYY, [PERIOD_TO]), FORMAT([PERIOD_TO], 'MM'))
THEN CONCAT(DATEPART(YYYY, [PERIOD_FROM]), FORMAT([PERIOD_FROM], 'MM'))
ELSE CONCAT(DATEPART(YYYY, [PERIOD_FROM]), FORMAT([PERIOD_FROM], 'MM'), ',', DATEPART(YYYY, [PERIOD_TO]), FORMAT([PERIOD_TO], 'MM'))
END AS Period_Of
使用带有 string_split 的交叉应用,我可以将行分成两部分,并使用另一个 case 语句,我可以根据从/到的时间段是否等于或大于拆分值来分配完整值,但这仅适用于两个月的差异我需要长达 48 个月。
我需要一个看起来像这样的输出:
ID PERIOD_FROM PERIOD_TO DAYS
------------------------------------------------------
1150524545 02/04/2019 30/04/2019 730
1150524545 01/05/2019 31/05/2019 730
1150524545 01/06/2019 30/06/2019 730
1150524545 01/07/2019 31/07/2019 730
………… ………… ………… ……
1150524545 01/02/2021 28/02/2021 730
1150524545 01/03/2021 31/03/2021 730
1150524545 01/04/2021 01/04/2021 730
任何帮助将不胜感激!
更新:
感谢 Serg 的帮助,我有了一个解决方案。我稍微调整了一下,以便 Period_To 在最后一个日期结束,但没有在我的请求中指定,因为这不是主要问题。
解决方案
使用数字表
-- Generate table of 1000 numbers starting 0
with t0(n) as (
select n
from (
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
) t(n)
),nmbs as(
select row_number() over(order by t1.n) - 1 n
from t0 t1, t0 t2, t0 t3
)
--
select Id
, dateadd(mm, nmbs.n, tbl.PERIOD_FROM) PERIOD_FROM
, case when ys.NextDate > tbl.PERIOD_TO then tbl.PERIOD_TO else ys.NextDate end PERIOD_TO
, DAYS
, tbl.PERIOD_TO originalPERIOD_TO
from [my table] tbl
join nmbs
on dateadd(mm, nmbs.n, tbl.PERIOD_FROM) <= tbl.PERIOD_TO
cross apply (select dateadd(mm, nmbs.n + 1, tbl.PERIOD_FROM) NextDate) ys
order by ID, dateadd(mm, nmbs.n, tbl.PERIOD_FROM);
推荐阅读
- mysql - 如果字符串具有符号'&',则查询不起作用
- python - Python:csv模块方言类的误导性文档
- express - 当“usernameField”设置为“email”时,Passport 返回“没有给出用户名”
- xamarin.forms - 如何在 Xamarin Forms 中打印字节数组?
- heroku - 预处理包含多条日志记录的消息
- android - 谷歌地图Android:圆圈上方的标记
- javascript - MDL - 单击时将 + 图标更改为 -?
- ios - 带有嵌套参数的 Alamofire POST 请求不返回任何内容
- azure-application-insights - Application Insights 获取每个按自定义属性分组的最新异常
- java - SELENIUM JAVA - 验证字符串的部分内容