SQL挑战!有效日期拆分
Posted
技术标签:
【中文标题】SQL挑战!有效日期拆分【英文标题】:SQL Challenge! Validity Dates Splitting 【发布时间】:2021-03-09 21:53:03 【问题描述】:我有一个表格,其中包含各种 id 的重叠有效期
startdate | enddate | id |
---|---|---|
6/10/2020 | 8/29/2022 | 1 |
10/23/2020 | 6/30/2021 | 2 |
10/23/2020 | 6/30/2023 | 3 |
仅使用 SQL(自连接,以及领先和滞后窗口函数等),我想拆分有效日期并复制每个条目并将其分配给正确的拆分。原因是因为我们将按开始和结束日期进行分组,以创建每个有效期的 json 列表。
startdate | enddate | id |
---|---|---|
6/10/2020 | 10/23/2020 | 1 |
10/23/2020 | 6/30/2021 | 1 |
10/23/2020 | 6/30/2021 | 2 |
10/23/2020 | 6/30/2021 | 3 |
6/30/2021 | 8/29/2022 | 1 |
6/30/2021 | 8/29/2022 | 3 |
8/29/2022 | 6/30/2023 | 3 |
我最终只是用 python 循环来实现它,但我知道必须有一种 sql 方式来实现它。
这是我放弃之前的。
with sorted_sch as( select
startdate,
enddate,
lead(startdate) over (partition by studioid, trainerid order by startdate) lead_start,
lead(enddate) over (partition by studioid, trainerid order by enddate) lead_end,
lag(startdate) over (partition by studioid, trainerid order by startdate) lag_start,
lag(enddate) over (partition by studioid, trainerid order by enddate) lag_end,
CASE WHEN lag(startdate) over (partition by studioid, trainerid order by startdate) is null then startdate
END imputed_startdate,
CASE WHEN lead(enddate) over (partition by studioid, trainerid order by enddate) is null then enddate
WHEN lag(startdate) over (partition by studioid, trainerid order by startdate) is not null then least(lag(startdate) over (partition by studioid, trainerid order by startdate),enddate)
END imputed_enddate
from ts )
select *, coalesce(s3.lag_end, s1.startdate) coalese_start, coalesce(s3.lag_end, s1.startdate) coalese_end,s1.startdate,s1.enddate,least(s1.enddate, s2.startdate) end
from sorted_sch s1
left join sorted_sch s2 on s2.startdate between s1.startdate and s1.enddate## and s1.id != s2.id
left join sorted_sch s3 on s3.enddate between s1.startdate and s1.enddate ##and s1.id != s3.id
【问题讨论】:
使用 SQL 总有办法,但办法可能不如 Python 那样整洁。 用您正在使用的数据库标记您的问题。 它需要是一个大的SQL语句吗?你能在 Python 中使用多个更简单的 SQL 语句吗? 我什至不明白这个问题。将一个不错的干净较长时期拆分为较短时期的逻辑是什么? 您使用的是哪种 DBMS 产品? “SQL”只是所有关系数据库都使用的一种查询语言,而不是特定数据库产品的名称。请为您正在使用的数据库产品添加tag。 Why should I tag my DBMS 【参考方案1】:很奇怪的问题。您只想根据所有日期拆分现有期间。因此,构造所有日期,然后使用连接来获取中间的每个日期:
with d as (
select startdate as dte
from sorted_sch
union -- on purpose to remove duplicates
select enddate
from sorted_sch
)
select d.dte as startdate, lead(d.dte, 1, ss.enddate) over (order by d.dte) as enddate,
ss.id
from sorted_sch ss join
d
on d.dte >= ss.startdate and d.dte < ss.enddate
order by startdate;
Here 是一个 dbfiddle。
【讨论】:
以上是关于SQL挑战!有效日期拆分的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server 无法使用有效字符串将字符串转换为日期时间