3

我有一个表,其中有 3 列id, start_time, end_time,其中start_timeend_timeDATE类型。

如何编写一个查询,它将对处理时间交错的记录​​进行分组。

例如,

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。

4

5 回答 5

1

oracle中有一个未记录的函数称为overlaps

select * 
from t1 , t2 
where (t1.start_time , t1.end_time) overlaps (t2.start_time , t2.end_time)

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

于 2013-07-26T13:27:47.190 回答
0

这是你要找的吗

SELECT  id ,           
    DATEDIFF(mi,start_time ,end_time+1) as interval
FROM table A 
ORDER BY (DATEDIFF(mi,start_time ,end_time+1))
于 2013-07-26T10:29:53.610 回答
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;

一个用于测试的 SQLfiddle

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

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

另一个 SQLfiddle

于 2013-07-26T11:09:10.173 回答
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.

于 2013-07-26T10:41:48.710 回答
0

以下是您正在寻找的内容:

赛贝斯

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() 函数来转换相同的。我希望这会有所帮助。

于 2013-07-26T11:07:18.973 回答