汇总特定日期范围内的日期

时间:2018-10-19 11:10:43

标签: oracle date range timeline

我有一个ID和日期都按彼此接近的日期分组的表

1       24/05/2010

10      18/06/2012
10      20/06/2012
10      21/06/2012

10      21/02/2014

10      04/07/2014

10      12/12/2016

1004    18/07/2016

1007    01/01/2017
1007    02/02/2017
1007    03/02/2017

1007    31/08/2017


create table tt ( id int, startdate date);  
Insert into TT values (1,'24/05/2010');
Insert into TT values (10,'18/06/2012');
Insert into TT values (10,'20/06/2012');
Insert into TT values (10,'21/06/2012');
Insert into TT values (10,'21/02/2014');
Insert into TT values (10,'04/07/2014');
Insert into TT values (10,'12/12/2016');
Insert into TT values (1004,'18/07/2016');
Insert into TT values (1007,'01/01/2017');
Insert into TT values (1007,'02/02/2017');
Insert into TT values (1007,'03/02/2017');
Insert into TT values (1007,'31/08/2017');

我正在尝试将重叠的日期和日期(最长间隔为90天)合并在一起,并在单行中列出它们,以ID分组显示日期范围,以便最终结果如下:

1       24/05/2010  24/05/2010
10      18/06/2012  21/06/2012
10      21/02/2014  21/02/2014
10      04/07/2014  04/07/2014
10      12/12/2016  12/12/2016
1004    18/07/2016  18/07/2016
1007    01/01/2017  03/02/2017
1007    31/08/2017  31/08/2017

2 个答案:

答案 0 :(得分:0)

我认为您必须使用递归查询来解决您的问题。这是我会用的:

WITH ord AS (SELECT id, startdate, ROW_NUMBER() over(PARTITION BY ID ORDER BY startdate) ord FROM tt) -- Connect every record with a number
   , rek(ord, id, startdate, enddate) AS 
         (SELECT ord, id, startdate, startdate FROM ord WHERE ord = 1 -- Take the first record of every group
          UNION ALL
          -- Then recursively take the next record
          SELECT rek.ord + 1
               , ord.id
               -- If the distance between old enddate and new startdate is <= 90 keep the startdate from the previous record otherwise take new one
               , CASE WHEN rek.enddate + 90 => ord.startdate
                      THEN rek.startdate
                      ELSE ord.startdate
                END
               , ord.startdate
            FROM rek
            JOIN ORD
              ON ord.ord = rek.ord+1
              AND ord.id = rek.id)
-- Cumulate data and keep only one record per id, startdate combination
SELECT id, startdate, MAX(enddate) enddate
  FROM rek
GROUP BY id, startdate
ORDER BY id, startdate

答案 1 :(得分:0)

好,这是另一种解决方案,仅使用LAGLEAD而不是递归查询:

WITH prv AS (SELECT id, startdate, lag(startdate) over (PARTITION BY id ORDER BY startdate) prev_date
             FROM tt)
   , NXT AS (SELECT id, startdate, lead(startdate) over (PARTITION BY id ORDER BY startdate) next_start
            FROM prv
           WHERE prev_date IS NULL OR prev_date < startdate - 90)
SELECT id,startdate
     , NVL((SELECT MAX(startdate) 
              FROM tt
             WHERE tt.id = nxt.id
               AND tt.startdate BETWEEN nxt.startdate AND nxt.next_start - 1)
          , startdate) enddate
  FROM nxt
相关问题