2

试图找出一个适用于多种情况的查询。简而言之,数据可能处于两种情况之一。假设我正在寻找在给定时间范围内发生的事件的记录 ID:2012 年 6 月 26 日上午 10:00 和 2012 年 6 月 27 日上午 11:00 数据库中的记录可能如下所示:

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

4 回答 4

2

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

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))
于 2012-06-27T17:53:34.527 回答
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 行。

于 2012-06-27T17:38:34.493 回答
0

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

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
)
于 2012-06-27T20:45:20.427 回答
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

(至少我是这样解释你的问题的)

于 2012-06-27T20:58:49.927 回答