子查询之间的SQL

时间:2012-08-09 08:15:40

标签: sql subquery

我想知道如何运行一个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

4 个答案:

答案 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答案的评论)


编辑以下编辑问题......

据我了解更改,只有在......

时才会返回一个事件
  • 事件时间至少(一个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)

答案 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语法,则使用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
    ) ;

答案 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"))
)