gpt4 book ai didi

sql - 将连续的日期有效期间隔连接在一起

转载 作者:行者123 更新时间:2023-12-04 23:51:01 26 4
gpt4 key购买 nike

我有一系列记录,其中包含一些具有时间有效性的信息(产品类型)。

我想将相邻的有效间隔融合在一起,前提是分组信息(产品类型)保持不变。我不能使用简单的 GROUP BYMINMAX ,因为某些产品类型(在示例中为 A )可以“离开”和“回来”。

使用 Oracle 11g。

MySQL的一个类似问题是:How can I do a contiguous group by in MySQL?

Input data :

| PRODUCT |                       START_DATE |                         END_DATE |
|---------|----------------------------------|----------------------------------|
| A | July, 01 2013 00:00:00+0000 | July, 31 2013 00:00:00+0000 |
| A | August, 01 2013 00:00:00+0000 | August, 31 2013 00:00:00+0000 |
| A | September, 01 2013 00:00:00+0000 | September, 30 2013 00:00:00+0000 |
| B | October, 01 2013 00:00:00+0000 | October, 31 2013 00:00:00+0000 |
| B | November, 01 2013 00:00:00+0000 | November, 30 2013 00:00:00+0000 |
| A | December, 01 2013 00:00:00+0000 | December, 31 2013 00:00:00+0000 |
| A | January, 01 2014 00:00:00+0000 | January, 31 2014 00:00:00+0000 |
| A | February, 01 2014 00:00:00+0000 | February, 28 2014 00:00:00+0000 |
| A | March, 01 2014 00:00:00+0000 | March, 31 2014 00:00:00+0000 |

Expected results :
| PRODUCT |                      START_DATE |                         END_DATE |
|---------|---------------------------------|----------------------------------|
| A | July, 01 2013 00:00:00+0000 | September, 30 2013 00:00:00+0000 |
| B | October, 01 2013 00:00:00+0000 | November, 30 2013 00:00:00+0000 |
| A | December, 01 2013 00:00:00+0000 | March, 31 2014 00:00:00+0000 |

查看完整版 SQL Fiddle .

最佳答案

这是一个缺口和孤岛问题。有多种方法可以接近它;这使用 leadlag解析函数:

select distinct product,
case when start_date is null then lag(start_date)
over (partition by product order by rn) else start_date end as start_date,
case when end_date is null then lead(end_date)
over (partition by product order by rn) else end_date end as end_date
from (
select product, start_date, end_date, rn
from (
select t.product,
case when lag(end_date)
over (partition by product order by start_date) is null
or lag(end_date)
over (partition by product order by start_date) != start_date - 1
then start_date end as start_date,
case when lead(start_date)
over (partition by product order by start_date) is null
or lead(start_date)
over (partition by product order by start_date) != end_date + 1
then end_date end as end_date,
row_number() over (partition by product order by start_date) as rn
from t
)
where start_date is not null or end_date is not null
)
order by start_date, product;

PRODUCT START_DATE END_DATE
------- ---------- ---------
A 01-JUL-13 30-SEP-13
B 01-OCT-13 30-NOV-13
A 01-DEC-13 31-MAR-14

SQL Fiddle

最里面的查询查看产品的前后记录,如果记录不连续,则仅保留开始和/或结束时间:
select t.product,
case when lag(end_date)
over (partition by product order by start_date) is null
or lag(end_date)
over (partition by product order by start_date) != start_date - 1
then start_date end as start_date,
case when lead(start_date)
over (partition by product order by start_date) is null
or lead(start_date)
over (partition by product order by start_date) != end_date + 1
then end_date end as end_date
from t;

PRODUCT START_DATE END_DATE
------- ---------- ---------
A 01-JUL-13
A
A 30-SEP-13
A 01-DEC-13
A
A
A 31-MAR-14
B 01-OCT-13
B 30-NOV-13

下一级选择删除那些处于中期的日期,其中两个日期都被内部查询清空,这给出:
PRODUCT START_DATE END_DATE
------- ---------- ---------
A 01-JUL-13
A 30-SEP-13
A 01-DEC-13
A 31-MAR-14
B 01-OCT-13
B 30-NOV-13

然后外部查询折叠那些相邻的对;我使用了创建重复项然后用 distinct 消除它们的简单方法。 ,但您可以通过其他方式做到这一点,例如将两个值放入一对行中,并将两个值保留在另一个空值中,然后用另一层选择消除那些值,但我认为这里可以区分。

如果您的实际用例有时间,而不仅仅是日期,那么您需要调整内部查询中的比较;而不是 +/- 1,可能是 1 秒的间隔,或者 1/86400(如果您愿意),但取决于您的值的精度。

关于sql - 将连续的日期有效期间隔连接在一起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22072376/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com