4

有効なセグメント内の時間を持つイベントを返す SQL クエリを実行する方法を知りたいです。

たとえば、私は2つのテーブルを持っています、

イベント

event_id event_time
0        134
1        434
2        4300

セグメント

segment_type segment_start_time segment_end_time
data1         100                130
data1         200                500
data1         700                8000
veto1         400                440
data2         150                450
data2         4000               5000
veto2         175                200

返すクエリが必要です

event_id event_time
1        434
2        4300

みたいなことを考えていた

SELECT * 
FROM event
WHERE 
    event.event_time > (SELECT segment.segment_start_time FROM segment)
    AND 
    event.event_time < (SELECT segment.segment_end_time FROM segment)

しかし、これは何も返しません。私は何を間違っていますか?

私がやりたい次のステップは、イベントの時間を見つけることです。

'data' セグメントの開始時刻と終了時刻の間 AND 'veto' セグメントの開始時刻と終了時刻の間

最後に、実際には 2 種類のデータ セグメントと拒否セグメントがあります。時間のあるイベントを返したい。

「data1」セグメントの開始時刻と終了時刻の間 AND

「data2」セグメントの開始時刻と終了時刻の間 AND

'veto1' セグメントの開始時刻と終了時刻の間でなく、かつ

「veto2」セグメントの開始時間と終了時間の間ではない

上記の表の例から、必要な出力は次のようになります

event_id event_time
2        4300
4

4 に答える 4

6

通常、イベント テーブルにはセグメント テーブルよりも多くのエントリがあると仮定します。

これにより、疑似コードを「すべてのセグメントについて、どのイベントが有効かをチェックする」ことができます。これにより、イベント テーブルでの範囲シークが可能になります。

SELECT
  event.event_id, event.event_time
FROM
  segment
INNER JOIN
  event
    ON  event.event_time >= segment.segment_start_time
    AND event.event_time <  segment.segment_end_time
GROUP BY
  event.event_id, event.event_time

の異なるエントリが重複GROUP BYする可能性がある場合にのみ必要です。segment


別のアプローチは、「イベントごとに、セグメントが重複しているかどうかを確認する」疑似コードを使用することです。

ただし、そうすると範囲シークは許可されません(@MarkByers の回答に関する私のコメントを参照してください)


編集質問への次の編集...

私が変更を理解している限り、イベントは次の場合にのみ返されるべきです...

  • イベント時間は少なくとも(1 つの data1 セグメントと 1 つの data2 セグメント)以内です。
  • イベント時間が (veto1 セグメントまたは veto2 セグメントのいずれか) 内にありません


SELECT
  event.event_id, event.event_time
FROM
  segment
INNER JOIN
  event
    ON  event.event_time >= segment.segment_start_time
    AND event.event_time <  segment.segment_end_time
GROUP BY
  event.event_id, event.event_time
HAVING
      0 = SUM(CASE WHEN segment_type = 'veto1' THEN 1 ELSE 0 END)
  AND 0 = SUM(CASE WHEN segment_type = 'veto2' THEN 1 ELSE 0 END)
  AND 1 = SUM(CASE WHEN segment_type = 'data1' THEN 1 ELSE 0 END)
  AND 1 = SUM(CASE WHEN segment_type = 'data2' THEN 1 ELSE 0 END)
于 2012-08-09T08:23:35.980 に答える
1

WHERE EXISTSまたは結合を使用します。

SELECT event_id, event_time
FROM event
WHERE EXISTS
(
   SELECT *
   FROM segment
   WHERE event.event_time BETWEEN segment_start_time AND segment_end_time
)
于 2012-08-09T08:18:33.790 に答える
0

セグメントが重複していない場合は、これを使用することもできます ( DBMS に構文が実装されていない場合は、独自の構文TOP またはその他の構文に適応します)。LIMITOFFSET / FETCH

SELECT
    event_id, event_time
FROM
    event AS e
WHERE 
    event_time <
    ( SELECT 
          s.segment_end_time
      FROM 
          segment AS s
      WHERE
          s.segment_start_time <= e.event_time
      ORDER BY 
          s.segment_start_time DESC
        OFFSET 1 ROWS
        FETCH NEXT 1 ROWS ONLY
    ) ;
于 2012-08-09T08:58:47.163 に答える
0

これは私が探しているクエリだと思いますが、100% 確実ではありません。

SELECT *
FROM event
WHERE EXISTS
(
   SELECT *
   FROM segment
   WHERE (event.time BETWEEN segment.start_time AND segment.end_time
                     AND segment.type IN ("data1", "data2"))
) AND EXISTS
(
   SELECT *
   FROM segment
   WHERE (event.time NOT BETWEEN segment.start_time AND segment.end_time 
                     AND segment.type ("veto1", "veto2"))
)
于 2012-08-09T14:00:28.197 に答える