在Oracle中对重叠时间间隔进行分组

9udxz4iz  于 2022-11-22  发布在  Oracle
关注(0)|答案(2)|浏览(170)

在Oracle 10g中有一个数据集包含date_fromdate_to列(或者更确切地说,只有date_from列,因为长度是恒定的)。
我需要折叠重叠的间隔,例如这些行:

date_from  date_to
2015-01-01 2015-01-10
2015-01-03 2015-01-11

需要变成:

2015-01-01 2015-01-11

我想知道是否有一种方法可以在不使用游标的情况下一次完成这个查询...我的查询很大,在边缘情况下仍然不能折叠所有内容。也许Oracle 10g中有一些SQL扩展可以解决这类问题,我可以使用它们?

ztigrdn8

ztigrdn81#

WITH data (date_from, date_to) AS (
    SELECT DATE'2015-01-01', DATE'2015-01-10' FROM DUAL UNION ALL
    SELECT DATE'2015-01-03', DATE'2015-01-11' FROM DUAL
)
SELECT
    min(date_from) date_from, max(date_to) date_to 
FROM (
    SELECT
        date_from, date_to,
        sum(merge) OVER (ORDER BY date_from) group_id
    FROM (
        SELECT
            date_from, date_to,
            case when date_from <= lag(date_to) OVER (ORDER BY date_from)
                 THEN 0
                 ELSE 1
            end as merge
        FROM data)
    ) intervals
GROUP BY group_id
ORDER BY min(intervals.date_from);
gojuced7

gojuced72#

我的数据还包含较小的非重叠日期范围,被一个大的日期范围吞没。此解决方案不包括这种情况。例如:

WITH
  DATA (DATE_FROM, DATE_TO) AS
    (SELECT DATE '2015-01-01', DATE '2015-01-20' FROM DUAL
     UNION ALL
     SELECT DATE '2015-01-02', DATE '2015-01-04' FROM DUAL
     UNION ALL
     SELECT DATE '2015-01-05', DATE '2015-01-07' FROM DUAL
     UNION ALL
     SELECT DATE '2015-01-08', DATE '2015-01-10' FROM DUAL
     UNION ALL
     SELECT DATE '2015-01-11', DATE '2015-01-13' FROM DUAL)
  --=======================================================================
  SELECT MIN(DATE_FROM) DATE_FROM, MAX(DATE_TO) DATE_TO
    FROM (
           SELECT DATE_FROM, DATE_TO, SUM(MERGE) OVER (ORDER BY DATE_FROM) GROUP_ID
             FROM (SELECT DATE_FROM, DATE_TO, CASE WHEN DATE_FROM <= LAG(DATE_TO) OVER (ORDER BY DATE_FROM) THEN 0 ELSE 1 END AS MERGE FROM DATA)
         ) INTERVALS
GROUP BY GROUP_ID
ORDER BY MIN(INTERVALS.DATE_FROM)

输出将生成4行,即仅生成一行:

DATE_FROM   DATE_TO
2015/01/01  2015/01/20
2015/01/05  2015/01/07
2015/01/08  2015/01/10
2015/01/11  2015/01/13

相关问题