我想知道如何运行一个SQL查询,该查询返回时间在有效段中的事件。
例如,我有两个表,
事件
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)
但这只是没有回报。我做错了什么?
我想要做的下一步是查找事件时间;
在'数据'段开始时间和结束时间AND之间 不在'否决'段开始时间和结束时间之间
最后,我实际上有两种类型的数据段和否决段。我想要返回有时间的事件;
在'data1'段开始时间和结束时间AND
之间在'data2'段开始时间和结束时间AND
之间不在'veto1'段开始时间和结束时间AND
之间不在'veto2'段开始时间和结束时间之间
所以从上面的示例表中,我想要的输出是
event_id event_time
2 4300
答案 0 :(得分:6)
我假设您通常会在事件表中拥有比在分段表中更多的条目。
这允许pseduo代码“为每个段,检查哪些事件有效”。这允许在事件表上进行范围搜索。
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答案的评论)。
编辑以下编辑问题......
据我了解更改,只有在......
时才会返回一个事件
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)
答案 1 :(得分: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
)
答案 2 :(得分:0)
如果段不重叠,您也可以使用它(如果您的DBMS已经实现了TOP
语法,则使用LIMIT
或OFFSET / 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
) ;
答案 3 :(得分:0)
我认为这是我正在寻找的查询,但我不是百分百肯定。
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"))
)