在时间范围内查找事件

时间:2012-06-27 16:49:13

标签: sql-server tsql

尝试找出可能适用于多种情况的查询。简而言之,数据可以是两种情况之一。假设我正在寻找在给定时间范围内发生的事件的record_id:6/26/2012 10:00 AM和6/27/2012 11:00 AM记录在数据库中可能如下所示:

Record    Event     Time
1         Start     6/26/2012 10:05AM
1         End       6/26/2012 10:45AM
2         Start     6/26/2012 09:55AM
2         End       6/26/2012 11:05AM

获取记录1很简单,只需使用between函数,但我很难找出一个返回记录1和2的查询。

建议?

4 个答案:

答案 0 :(得分:1)

您可以简单地扩大范围,但这可能会带回与您想要的不同的记录。

SELECT  RECORD, EVENT, TIME 
FROM SO_RecordEvent AS R
WHERE TIme BETWEEN  '6/26/2012 9:55AM'  AND '6/26/2012 11:06AM'

这将返回任何具有该范围内的开始或结束时间的记录,包括超出范围的相关记录(换句话说,记录只有一次在该范围内 - 但在之前或结束时开始之后 - 它仍将显示其外的开始或结束时间)并允许您缩短范围。

 ;WITH X AS 
 (
    SELECT RECORD,EVENT,TIME FROM SO_RecordEvent 
 )
 SELECT R.RECORD,R.EVENT,R.TIME 
 FROM SO_RecordEvent AS R
 INNER JOIN X ON R.Record = X.Record
 WHERE X.TIme BETWEEN  '6/26/2012 10:05AM'  AND '6/26/2012 11:05AM'
 GROUP BY R.RECORD,R.EVENT,R.TIME

但我认为你可能真的想要这样的东西,它真正为你提供了在那段时间内开始的一切,即使它在范围之外开始和结束,就像你的记录2例子一样。

修改

改变逻辑 - 而不是解决决定以这种方式思考的情况 - 在开始和结束时开始的任何事情,在开始和结束时结束的任何事情,以及在之前和结束之后开始的任何事情。我认为这涵盖了在此期间运行的任何事情(在结束之前开始,开始和结束之内,开始之内和结束之后,开始之前和结束之后)

  SELECT X.RECORD,X.TIME AS STARTTIME,Y.TIME AS ENDTIME 
  FROM SO_RecordEvent AS X
  INNER JOIN SO_RecordEvent Y ON Y.Record = X.Record AND Y.EVENT = 'END'
  WHERE  X.EVENT = 'START'
  AND 
  ((X.TIME >= '6/26/2012 10:00AM' AND X.TIME <= '6/26/2012 11:00AM')
  OR (Y.TIME >= '6/26/2012 10:00AM' AND Y.TIME <= '6/26/2012 11:00AM')
  OR (X.TIME <= '6/26/2012 10:00AM' AND Y.TIME >= '6/26/2012 11:00AM'))

要使用的变量:

 DECLARE @START datetime, @END datetime
 SET @START = '6/26/2012 10:00AM'
 SET @END = '6/26/2012 11:00AM'

   SELECT X.RECORD,X.TIME AS STARTTIME,Y.TIME AS ENDTIME 
   FROM SO_RecordEvent AS X
   INNER JOIN SO_RecordEvent Y ON Y.Record = X.Record AND Y.EVENT = 'END'
   WHERE  X.EVENT = 'START'
   AND 
  ((X.TIME >= @START AND X.TIME <= @END)
  OR (Y.TIME >= @START AND Y.TIME <= @END)
  OR (X.TIME <= @START AND Y.TIME >= @END))

答案 1 :(得分:0)

我可能会加入桌子 - 就像这样:

SELECT *
FROM
    Table leftside
    JOIN Table rightside
        ON leftside.Record = rightside.Record
WHERE
    leftside.Event = 'Start'
    and rightside.Event = 'End'
    and [whatever time you want] >= leftside.Time
    and [whatever time you want] <= rightside.Time

编辑:演示示例

create table thingy (
    record int,
    event varchar(10),
    time datetime )

insert thingy (record,event,time) values (1,'Start','6/26/2012 10:05AM')
insert thingy (record,event,time) values (1,'End','6/26/2012 10:45AM ')
insert thingy (record,event,time) values (2,'Start','6/26/2012 09:55AM')
insert thingy (record,event,time) values (2,'End','6/26/2012 11:05AM')

DECLARE @mytime datetime
SET @mytime = '6/26/2012 9:58AM'

SELECT * 
FROM 
        thingy leftside 
    JOIN thingy rightside 
        ON leftside.Record = rightside.Record 
WHERE 
    leftside.Event = 'Start' 
    and rightside.Event = 'End' 
    and @mytime >= leftside.Time 
    and @mytime <= rightside.Time 

SET @mytime = '6/26/2012 10:10AM'
SELECT * 
FROM 
    thingy leftside 
    JOIN thingy rightside 
        ON leftside.Record = rightside.Record 
WHERE 
    leftside.Event = 'Start' 
    and rightside.Event = 'End' 
    and @mytime >= leftside.Time 
    and @mytime <= rightside.Time 

似乎给出我期望的东西 - 第一个查询为1行,第二个为2。

答案 2 :(得分:0)

获取属于给定范围内的所有事件的记录#:

SELECT Record
FROM atable
WHERE Time BETWEEN @StartTime AND @EndTime

现在只需获取其记录#s与上述查询结果集中的记录匹配的所有行,即如下所示:

SELECT *
FROM atable
WHERE Record IN (
  SELECT Record
  FROM atable
  WHERE Time BETWEEN @StartTime AND @EndTime
)

答案 3 :(得分:0)

最简单的方法是使用以下方法:

WITH recs AS (
SELECT Record, MIN(tme) AS startTime, MAX(tme) AS endTime
FROM records
GROUP BY Record
)
SELECT * FROM
records
WHERE startTime >= @eventsAfter
AND endTime <= @eventsBefore

(这是我解释你的问题的方式,至少)