按sql server中最接近的时差排序

时间:2018-01-09 12:01:19

标签: sql sql-server database

我想通过最接近的时差来获取记录顺序。

我已经计算了order by子句中的时差,这会导致性能问题,因为表有大约2M条记录。

注意:在我的实际查询中,没有连接,表只有13列。

获取此样本数据:

CREATE TABLE yourtable
    ([ID] int, [User] varchar(5), [ScheduleOn] datetime)
;

INSERT INTO yourtable
    ([ID], [User], [ScheduleOn])
VALUES
    (1, 'User1', '2018-01-09 11:50:03.103'),
    (2, 'User2', '2018-01-09 11:38:03.103'),
    (3, 'User3', '2018-01-09 11:42:03.103'),
    (4, 'User4', '2018-01-09 11:45:03.103'),
    (5, 'User5', '2018-01-09 11:43:03.103'),
    (6, 'User6', '2018-01-09 11:44:03.103'),
    (7, 'User7', '2018-01-09 11:40:03.103')
;

这是我的示例查询。

ScheduleOn是日期时间的类型。

Declare @currentDate datetime = '2018-01-09 11:42:03.103'

select *, ABS(datediff(mi,@currentDate,ScheduleOn)) AS JustToSee from yourtable 

order by ABS(datediff(mi,@currentDate,ScheduleOn))

我想知道,是否有其他人通过最接近的时差获得记录顺序。

SQL Fiddle

3 个答案:

答案 0 :(得分:2)

虽然您尚未回复评论中提出的问题,但我认为您或其他人可能会看到提及的查询类型。

给出的示例很昂贵,因为在ABS(DATEDIFF())操作之后,数据被认为是乱序的。这意味着对数据进行排序会变得很昂贵(排序200万行)

但是,只有那些最接近@currentDate值的行才有意义,在必须应用排序之前,可以限制样本大小。

WITH
  closest_100_each_side
(
  SELECT TOP(100) *, ScheduleOn - @currentDate AS diff FROM yourTable WHERE ScheduleOn >= @currentDate ORDER BY ScheduleOn ASC
  UNION ALL
  SELECT TOP(100) *, @currentDate - ScheduleOn AS diff FROM yourTable WHERE ScheduleOn <  @currentDate ORDER BY ScheduleOn DESC
)
SELECT TOP(100)
  *
FROM
  closest_100_each_side
ORDER BY
  diff ASC

ScheduleOn上使用适当的索引时,CTE中的两个查询变得微不足道,最后的查询现在只需要对200行进行排序以找到最接近的100行。

比将TOP(100)简单地应用到现有查询更快。

因此,理解数据的用途以及在执行查询后如何实际使用它变得非常重要。这一小段信息可能允许对查询进行微小更改,以显着提高性能。

答案 1 :(得分:0)

只要MS SQL DATETIME在内部是2个整数,你就可以这样做:

Declare @currentDate datetime = '2018-01-09 11:42:03.103'
Declare @currentDateFloat float = CONVERT(float, @currentDate)

select *, ABS(Cast((@currentDateFloat - ScheduleOn) as Float)) AS JustToSee 
from yourtable 
order by ABS(Cast((@currentDateFloat - ScheduleOn) as Float))

但我怀疑它会更快,因为我已经检查了实际的执行计划,它与您的查询相同。

答案 2 :(得分:-1)

不确定,但你可以试试这个:

WITH CTE AS (
select *, ABS(datediff(mi,@currentDate,ScheduleOn)) AS JustToSee from 
yourtable )

SELECT * FROM CTE ORDER BY JustToSee