对于你的T-SQL大师:
我有下表:
ID Arrival
1 06:16:00
2 06:17:00
3 07:19:00
4 08:21:00
5 10:22:00
6 13:21:00
7 20:22:00
假设时间目前是08:00 AM,我想在记录之前和之后选择2条记录,最接近现在。结果应返回ID为2,3,4,5和6的记录。
获取ID = 4的记录之前和之后的记录是直截了当的,但到目前为止,我无法弄清楚如何将完整集作为同一查询的一部分返回。我有这两个选择语句:
SELECT TOP(2) * FROM Schedules
where (datepart(hour, Arrival) - datepart(hour, getdate()))*60 + datepart(minute, Arrival) - datepart(minute, getdate()) < 0
order by (datepart(hour, Arrival) - datepart(hour, getdate()))*60 + datepart(minute, Arrival) - datepart(minute, getdate())
SELECT TOP(2) * FROM Schedules
where (datepart(hour, Arrival) - datepart(hour, getdate()))*60 + datepart(minute, Arrival) - datepart(minute, getdate()) >= 0
order by (datepart(hour, Arrival) - datepart(hour, getdate()))*60 + datepart(minute, Arrival) - datepart(minute, getdate()) asc
返回前后的记录。我尝试在两个语句上使用union,但这需要删除第一个order by子句,这会使我的查询条件无效。
任何想法都会有所帮助,谢谢。
答案 0 :(得分:1)
如果到达时间或之后,我们可以使用ROW_NUMBER
进行分区,并按到达时间和输入时间之差的绝对值进行排序。
DECLARE @CurrentTime as time
SET @CurrentTime = '08:00 AM'
DECLARE @Schedules table (id int, arrival time)
INSERT INTO @Schedules
VALUES (1 , '06:16:00' ),
(2, '06:17:00' ),
(3, '07:19:00'),
(4, '08:21:00'),
(5, '10:22:00'),
(6, '13:21:00'),
(7, '20:22:00')
DECLARE @closestTime as time
SELECT TOP 1 @closestTime = arrival FROM @Schedules ORDER BY ABS(DATEDIFF(mi, @CurrentTime ,arrival))
;WITH cte
AS (SELECT id,
arrival,
Row_number() OVER (PARTITION BY (CASE WHEN @closestTime > arrival THEN 1
WHEN @closestTime < arrival THEN 2 END)
ORDER BY Abs(Datediff(mi, @closestTime, arrival))) rn
FROM @Schedules)
SELECT *
FROM cte
WHERE rn < 3
OR arrival = @closestTime
ORDER BY id
结果
id arrival rn
----------- ---------------- --------------------
2 06:17:00.0000000 2
3 07:19:00.0000000 1
4 08:21:00.0000000 1
5 10:22:00.0000000 1
6 13:21:00.0000000 2
请参阅此data.se query
的工作示例答案 1 :(得分:0)
您可以尝试以下方法吗?我已经测试过,得到了你想要的结果
create table Arriavel (ID int, Arr_time time)
insert into Arriavel values (1, '06:16:00')
insert into Arriavel values (2, '06:17:00')
insert into Arriavel values (3, '07:19:00')
insert into Arriavel values (4, '08:21:00')
insert into Arriavel values (5, '10:22:00')
insert into Arriavel values (6, '13:21:00')
insert into Arriavel values (7, '20:22:00')
declare @cur_time time
set @cur_time = '08:00:00'
select max(arr_time) arr_time
from Arriavel
where arr_time < @cur_time
union all
select min(arr_time) arr_time
from Arriavel
where arr_time > @cur_time