3

とタイプの3 つの列を持つテーブルがid, start_time, end_timeありstart_timeます。end_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およびインターリーブされています。

どうすればこれを達成できますか?

私はオラクル11gを使用しています。

4

5 に答える 5

1

オラクルには文書化されていない関数があります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

これは、共通のテーブル式を最後に再帰クエリと組み合わせて実行する必要があります。

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

TO_DATE()関数を使用して同じものを変換しない場合、上記の回答は列をDATEデータ型と想定しています。これが助けになることを願っています。

于 2013-07-26T11:07:18.973 に答える