【问题标题】:Aggregate dates within specific day range特定日期范围内的汇总日期
【发布时间】:2018-10-19 11:10:43
【问题描述】:

我有一个表格,其中包含按彼此接近的日期分组的 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

【问题讨论】:

  • 提示:使用 max、min 和 group by 来满足您的要求。如果您遇到任何问题,请尝试告诉我们
  • 感谢回复,但这不会达到我的目标: select studyid, min(startdate), max(startdate) from temp_ste group by studyid;将产生: 1 24/05/2010 00:00 24/05/2010 00:00 10 18/06/2012 00:00 12/12/2016 00:00 1004 18/07/2016 00:00 18/07/ 2016 00:00 1007 01/01/2017 00:00 31/08/2017 00:00
  • 这个问题 100% 重复,但我无法快速找到匹配项。对于答案,通常使用lag() 和分析型sum(),例如here
  • 感谢@ponderstibbons 完美运行!

标签: oracle date range timeline


【解决方案1】:

好的,这是另一种解决方案,仅使用 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

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      • 1970-01-01
      • 1970-01-01
      • 2013-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多