自 DST 日期以来获取行的正确方法?
Proper way of getting rows since a date accounting for DST?
我有一个日期时间列 changedate
,我需要用它来获取上周自下午 1 点以来更改的行。不幸的是,本专栏是当地时间 (EST)。服务器是 Microsoft SQL Server 2016.
这是我现在的查询:
DECLARE @since datetime = DATEADD(week,-1,SMALLDATETIMEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()), 13, 0)) AT TIME ZONE 'Eastern Standard Time'
SELECT * FROM table WHERE changedate AT TIME ZONE 'Eastern Standard Time' >= @since
由于我对列和 @since
都使用了 AT TIME ZONE
,这是否可以正确说明 DST 更改?根据我找到的文档,这是我的理解,但我不能 100% 确定它是否是这样工作的,或者我是否遗漏了什么。
首先,找出您要比较的时间:
-- Get the current date in the given time zone
DECLARE @today date = convert(date, sysdatetimeoffset() AT TIME ZONE 'Eastern Standard Time')
-- Get the date one week ago
DECLARE @dateOneWeekAgo date = DATEADD(week, -1, @today)
-- Join the date with the desired time (local to the same time zone)
DECLARE @since datetime = convert(datetime, @dateOneWeekAgo) + convert(datetime, timefromparts(1, 0, 0, 0, 0))
那就比较一下:
SELECT * FROM table WHERE changedate >= @since
假设您的 changedate
字段是 datetime
或 datetime2
。如果是datetimeoffset
,你应该先将目标值转换成同一时区的datetimeoffset
,然后用它来代替:
DECLARE @sinceDTO datetimeoffset = @since AT TIME ZONE 'Eastern Standard Time'
关于你在问题中给出的方法,有两个问题:
getdate()
给出基于服务器本地时区的时间。东部时间可能不是同一天。
永远不要对 where 子句中的 table 字段应用函数(无论是 AT TIME ZONE
之类的内部函数还是其他函数),因为它使查询 non-sargable。换句话说,SQL 必须扫描整个 table,而不是使用索引。 table 越大,查询速度越慢。
我有一个日期时间列 changedate
,我需要用它来获取上周自下午 1 点以来更改的行。不幸的是,本专栏是当地时间 (EST)。服务器是 Microsoft SQL Server 2016.
这是我现在的查询:
DECLARE @since datetime = DATEADD(week,-1,SMALLDATETIMEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), DAY(GETDATE()), 13, 0)) AT TIME ZONE 'Eastern Standard Time'
SELECT * FROM table WHERE changedate AT TIME ZONE 'Eastern Standard Time' >= @since
由于我对列和 @since
都使用了 AT TIME ZONE
,这是否可以正确说明 DST 更改?根据我找到的文档,这是我的理解,但我不能 100% 确定它是否是这样工作的,或者我是否遗漏了什么。
首先,找出您要比较的时间:
-- Get the current date in the given time zone
DECLARE @today date = convert(date, sysdatetimeoffset() AT TIME ZONE 'Eastern Standard Time')
-- Get the date one week ago
DECLARE @dateOneWeekAgo date = DATEADD(week, -1, @today)
-- Join the date with the desired time (local to the same time zone)
DECLARE @since datetime = convert(datetime, @dateOneWeekAgo) + convert(datetime, timefromparts(1, 0, 0, 0, 0))
那就比较一下:
SELECT * FROM table WHERE changedate >= @since
假设您的 changedate
字段是 datetime
或 datetime2
。如果是datetimeoffset
,你应该先将目标值转换成同一时区的datetimeoffset
,然后用它来代替:
DECLARE @sinceDTO datetimeoffset = @since AT TIME ZONE 'Eastern Standard Time'
关于你在问题中给出的方法,有两个问题:
getdate()
给出基于服务器本地时区的时间。东部时间可能不是同一天。永远不要对 where 子句中的 table 字段应用函数(无论是
AT TIME ZONE
之类的内部函数还是其他函数),因为它使查询 non-sargable。换句话说,SQL 必须扫描整个 table,而不是使用索引。 table 越大,查询速度越慢。