SQL查询:使用元组列表进行搜索

时间:2014-10-11 05:25:30

标签: sql sql-server

我在SQLServer中有一个下表(简化版)。

Table Events
-----------------------------------------------------------
| Room | User | Entered             | Exited              |
-----------------------------------------------------------
| A    | Jim  | 2014-10-10T09:00:00 | 2014-10-10T09:10:00 | 
| B    | Jim  | 2014-10-10T09:11:00 | 2014-10-10T09:22:30 | 
| A    | Jill | 2014-10-10T09:00:00 | NULL                | 
| C    | Jack | 2014-10-10T09:45:00 | 2014-10-10T10:00:00 | 
| A    | Jack | 2014-10-10T10:01:00 | NULL                |
 .
 .
 . 

我需要创建一个查询,在给定的时间戳中返回人的行踪。 举个例子:哪里(吉姆在2014-10-09T09:05:00),(吉姆在2014-10-10T09:01:00),(吉尔在2014-10-10T09:10:00),...

结果集必须包含给定的用户和时间戳以及找到的房间(如果有)。

------------------------------------------
| User | Timestamp           | WasInRoom |
------------------------------------------
| Jim  | 2014-10-09T09:05:00 | NULL      |
| Jim  | 2014-10-09T09:01:00 | A         |
| Jim  | 2014-10-10T09:10:00 | A         |

用户 - 时间戳元组的数量可以是> 10 000.

当前实现从Events表中检索所有记录,并在Java代码中进行搜索。我希望我能把这个逻辑推向SQL。但是如何?

我正在使用MyBatis框架来创建SQL查询,因此可以将元组内联到查询中。

3 个答案:

答案 0 :(得分:1)

基本查询是:

select e.*
from events e
where e.user = 'Jim' and '2014-10-09T09:05:00' >= e.entered and ('2014-10-09T09:05:00' <= e.exited or e.exited is NULL) or
      e.user = 'Jill' and '2014-10-10T09:10:00 >= e.entered and ('2014-10-10T09:10:00' <= e.exited or e.exited is NULL) or
     . . .;

SQL Server可以处理大量可疑的查询,因此您可以继续这样做。但是,如果表中已有名称/时间值(或者是查询结果),则使用join

select ut.*, t.*
from usertimes ut left join
     events e
     on e.user = ut.user and 
        ut.thetime >= et.entered and (ut.thetime <= exited or ut.exited is null);

请注意此处使用left join。它确保所有原始行都在结果集中,即使没有匹配项也是如此。

答案 1 :(得分:1)

我认为Jonas和Gordon的答案让我走上正轨。

这是一个似乎可以完成工作的查询:

CREATE TABLE #SEARCH_PARAMETERS(User VARCHAR(16), "Timestamp" DATETIME)
INSERT INTO #SEARCH_PARAMETERS(User, "Timestamp") 
VALUES 
('Jim', '2014-10-09T09:05:00'),
('Jim', '2014-10-10T09:01:00'),
('Jill', '2014-10-10T09:10:00')

SELECT #SEARCH_PARAMETERS.*, Events.Room FROM #SEARCH_PARAMETERS
LEFT JOIN Events
ON #SEARCH_PARAMETERS.User = Events.User AND
   #SEARCH_PARAMETERS."Timestamp" > Events.Entered AND
   (Events.Exited IS NULL OR Events.Exited > #SEARCH_PARAMETERS."Timestamp"

DROP TABLE #SEARCH_PARAMETERS

答案 2 :(得分:0)

通过声明(user,timestamp)元组的表值参数类型,编写一个表值用户定义函数应该很简单,该函数通过连接参数表和Events表返回所需的结果。见http://msdn.microsoft.com/en-us/library/bb510489.aspx

由于您正在使用MyBatis,因此可能更容易为查询中的元组内联生成元组表变量并加入其中。