Postgres SQL组通过重叠句点

时间:2017-07-18 15:45:06

标签: sql postgresql group-by postgresql-9.3 overlap

我尝试按重叠时段对数据进行分组,如果它们完全覆盖较大的时段,则只保留较小的时段。

这是一个更清晰的例子。 让我们假设这个结构和数据

drop table chload.testdata
create table chload.testdata
( 
  id int,
  startdate date,  
  enddate date,
  val text
);

insert into chload.testdata (id,startdate,enddate,val) values
-- included periods
(1, to_date('2009-01-01','YYYY-MM-DD'), to_date('2010-01-01','YYYY-MM-DD'), 'incA'),
(2, to_date('2010-01-01','YYYY-MM-DD'), to_date('2011-01-01','YYYY-MM-DD'), 'incB'),
(3, to_date('2011-01-01','YYYY-MM-DD'), to_date('2012-01-01','YYYY-MM-DD'), 'incC'),

-- isolated period
(4, to_date('2008-01-01','YYYY-MM-DD'), to_date('2009-01-01','YYYY-MM-DD'), 'isoD'),

-- Covering periods
(5, to_date('2009-01-01','YYYY-MM-DD'), to_date('2011-01-01','YYYY-MM-DD'), 'covE'),
(6, to_date('2009-01-01','YYYY-MM-DD'), to_date('2012-01-01','YYYY-MM-DD'), 'covF')
;

现在游戏是为了得到那个结果

2009-01-01  2010-01-01  incA covE covF
2010-01-01  2011-01-01  incB covE covF
2011-01-01  2012-01-01  incC covF
2008-01-01  2009-01-01  isoD

注意:如果被包含的期间完全“覆盖”,则不会显示覆盖期。

提前致谢:)

2 个答案:

答案 0 :(得分:1)

尝试使用此

SELECT distinct lg1.startdate, lg1.enddate, lg1.val || ' '|| lg2.val
  FROM testdata lg1,testdata lg2
where  lg1.enddate<= lg2.enddate and  lg1.startdate>= lg2.startdate and  lg1.id!= lg2.id
order by 3

答案 1 :(得分:0)

尝试使用此

WITH enddates AS
  (SELECT DISTINCT lg1.startdate,
                   lg1.enddate,
                   lg1.val AS pg,
                   string_agg(lg2.val,' ') AS RESULT
   FROM chload.testdata lg1,
        chload.testdata lg2
   WHERE (lg1.enddate<= lg2.enddate
          AND lg1.startdate>= lg2.startdate
          AND lg1.id!= lg2.id
          AND lg1.val NOT IN
            (SELECT lg2.val
             FROM chload.testdata lg1,
                  chload.testdata lg2
             WHERE lg1.enddate<= lg2.enddate
               AND lg1.startdate>= lg2.startdate
               AND lg1.id!= lg2.id))
   GROUP BY 1,
            2,
            3
   ORDER BY 3)
SELECT DISTINCT startdate,
                enddate,
                pg,
                pg||' '|| RESULT AS RESULT
FROM enddates
UNION ALL
SELECT lg.startdate,
       lg.enddate,
       lg.val AS pg,
       lg.val AS RESULT
FROM chload.testdata lg
WHERE lg.val NOT IN
    (SELECT lg1.val
     FROM chload.testdata lg1,
          chload.testdata lg2
     WHERE lg1.enddate<= lg2.enddate
       AND lg1.startdate>= lg2.startdate
       AND lg1.id!= lg2.id)
  AND lg.val NOT IN
    (SELECT lg2.val
     FROM chload.testdata lg1,
          chload.testdata lg2
     WHERE lg1.enddate<= lg2.enddate
       AND lg1.startdate>= lg2.startdate
       AND lg1.id!= lg2.id)
ORDER BY 3