4

我想知道如何运行一个返回事件的 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)

但这只是什么都不返回。我究竟做错了什么?

我想做的下一步是找到事件时间;

在“数据”段开始时间和结束时间之间,而不是在“否决”段开始时间和结束时间之间

最后,我实际上有两种类型的数据段和否决段。我想返回有时间的事件;

在“data1”段开始时间和结束时间之间和

在“data2”段开始时间和结束时间之间和

不在“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 回答的评论)


编辑以下编辑问题...

据我了解这些更改,只有在以下情况下才应返回事件...

  • 事件时间至少在(一个 data1 段和一个 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 回答