SQL查询以查找交错的记录

时间:2013-07-26 10:11:22

标签: sql oracle plsql

我的表格有3列id, start_time, end_time,其中start_timeend_time属于DATE类型。

如何编写查询,将查询处理时间为交错的记录​​。

例如,

id    start_time         end_time
---------------------------------------------------------
1   25/07/2013 10:30:00  25/07/2013 11:30:00
2   25/07/2013 11:00:00  25/07/2013 12:00:00
3   25/07/2013 11:15:00  25/07/2013 12:30:00
4   25/07/2013 14:30:00  25/07/2013 15:30:00
5   25/07/2013 10:30:00  25/07/2013 11:15:00
6   25/07/2013 13:30:00  25/07/2013 14:45:00

此处,id 1,2,3,5是交错的,4,6和交错。

我怎样才能做到这一点?

我正在使用Oracle 11g。

5 个答案:

答案 0 :(得分:1)

oracle中有一个名为overlaps

的未记录函数
select * 
from t1 , t2 
where (t1.start_time , t1.end_time) overlaps (t2.start_time , t2.end_time)

我强烈建议不要使用未记录的功能 但知道它仍然很酷!

答案 1 :(得分:0)

这是你要找的那个

SELECT  id ,           
    DATEDIFF(mi,start_time ,end_time+1) as interval
FROM table A 
ORDER BY (DATEDIFF(mi,start_time ,end_time+1))

答案 2 :(得分:0)

这是一种方法,您可以识别与另一个具有较早start_time的记录交错的每条记录。这是"开始"交错组。然后,获取此计数的累计总和,并标识每个组。

您可以使用自联接和窗口函数执行此操作:

select t.*,
       count(starts.id) over (order by t.start_time) as InterleaveGrouping
from t left outer join
     (select distinct t.id
      from t left outer join
           t tprev
           on t.start_time < tprev.end_time and t.end_time > tprev.start_time and
              t.start_time > tprev.start_time
      where tprev.id is null
     ) starts
     on t.id = starts.id;

如果您需要有关这些组的信息,可以使用group by InterleaveGrouping

答案 3 :(得分:0)

您正在寻找以下内容:

  

的Sybase

select distinct 
    t1.*
from
    table_name t1,
    table_name t2
where
    datediff(ss,t2.start_time,t1.start_time) > 0
and datediff(ss,t2.end_time,t1.start_time) < 0
union
select distinct 
    t1.*
from
    table_name t1,
    table_name t2
where
    datediff(ss,t2.start_time,t1.start_time) < 0
and datediff(ss,t2.start_time,t1.end_time) > 0
order by t1.start_time
  

甲骨文:

select distinct 
    t1.*
from
    table_name t1,
    table_name t2
where
    t1.START_DATE - t2.START_DATE > 0
and t1.START_DATE - t2.END_DATE < 0
union
select distinct 
    t1.*
from
    table_name t1,
    table_name t2
where
    t1.START_DATE - t2.START_DATE < 0
and t1.END_DATE - t2.START_DATE > 0

上面的答案假设列为DATE数据类型,如果它们不使用TO_DATE()函数进行转换。我希望这有帮助。

答案 4 :(得分:0)

这应该这样做,将公共表表达式与最后的递归查询相结合;

WITH cte1 AS (
  SELECT a."id" id, a."start_time" start_time, a."end_time" end_time,
  ROW_NUMBER() OVER (ORDER BY a."start_time", a."end_time") rn
  FROM Table1 a
), cte2 AS (
  SELECT id, start_time, end_time, 
    (SELECT MIN(id) FROM cte1 b WHERE b.id<a.id AND a.start_time<b.end_time) overlap
  FROM cte1 a
), cte3 (id, overlap) AS (
   SELECT id, id overlap FROM cte2 WHERE overlap IS NULL
   UNION ALL 
   SELECT nplus.id, n.overlap
   FROM cte2 nplus
   JOIN cte3 n
     ON nplus.overlap = n.id
)
SELECT * FROM cte3;

An SQLfiddle to test with

编辑:反映一下后,这更简单:)

SELECT DISTINCT t1.*, 
    COUNT(DECODE(t2.id, NULL, 0, NULL)) 
     OVER (ORDER BY t1.start_time, t1.end_time) igroup
FROM Table1 t1 LEFT JOIN Table1 t2 
  ON t1.id <> t2.id AND t1.start_time >= t2.start_time 
                    AND t1.start_time <  t2.end_time
ORDER BY t1.start_time, t1.end_time

Another SQLfiddle