SQL Server - 检查特定日期+时间是否在两个日期时间变量之间

3

我可以为您翻译,以下是内容:

我在数据库表中有两个日期时间列:@Start 和 @End。

这两个列都包含日期和时间,例如:

@Start: 2018-10-01 19:00:00
@End: 2018-10-10 23:59:00

我想知道当前日期是否恰好处于两个日期时间之间,考虑日期和时间。
例如,2018-10-08 16:372018-10-10 23:59:00 将匹配此范围, 而2018-10-11 00:00:00则不会。 (在这种情况下,该日期比结束日期晚一分钟,因此不在我的日期时间范围内)。
SELECT Id FROM Table1 WHERE GETDATE() BETWEEN Start AND End

我在真实代码中不使用GETDATE(),而是使用参数。问题在于当前日期参数可能包含秒和毫秒,例如23:59: 59.123。我的代码将这样的日期视为不符合给定范围。但我不关心秒和毫秒。
是否有解决方法?
更新:
我想要实现的精度分钟。因此,我甚至不需要考虑秒或毫秒。我将使用的日期时间格式是 'yyyy-MM-dd hh-mm',但我不知道如何使用BETWEEN子句将开始和结束转换为所示格式,以便可以比较日期。

5
你的代码应该在任何版本的SQL Server上都能正常运行。 - Gordon Linoff
3
在你的查询中,GetDate() 始终返回当前日期和时间。但为了从表中获取记录,请使用表列而不是 GetDate() - Nareen Babu
2
Between在日期时间检查方面真的很糟糕。这里有一个关于这个主题的很好的讨论。https://sqlblog.org/2011/10/19/what-do-between-and-the-devil-have-in-common - Sean Lange
1
@asaf 您的查询是完美的。唯一可能出现的问题是当变量的数据类型为 datetime 且您尝试插入毫秒值,例如 00:00:00.00100:00:00.002 时。这些值会被四舍五入,最终得到的结果是 00:00:00.00000:00:00.003 - Salman A
1
啊,这就是重点。最后的毫秒数。你的 EndDate 是否包含这些毫秒?不是的。(PS:你的问题是否告诉我们有关毫秒或给定样本数据的任何信息?恐怕不是。)常见的解决方案是使用下一个日期的“00:00:00”的 <,而不是为了与 23.59.59.(9) 的 <= 而战。 - Ivan Starostin
显示剩余11条评论
4个回答

3
您似乎需要这个逻辑:
WHERE GETDATE() >= Start
  AND GETDATE() < DATEADD(minute, 1, End)

假设 End 的时间部分为 23:59:00,则它覆盖了从 23:59:0023:59:59.999...999 之间所有可能的值。

我采纳了你的建议,它起作用了!非常感谢你!此外,BETWEEN解决方案似乎也最终奏效了。 - Asaf Epelbaum

1
尝试
SELECT Id FROM Table1 WHERE 
         CONVERT(varchar(16),GETDATE(),121) BETWEEN 
                  CONVERT(varchar(16),[Start], 121) 
                  AND 
                  CONVERT(varchar(16),[END],121);

无字符串的四舍五入示例

DECLARE @GetDateMinutes as datetime2;

DECLARE @X as datetime2 = getdate();

--round to minutes, could be made into a function
SET @GetDateMinutes = dateadd(minute,datepart(minute,@x),dateadd(hour, datepart(hour,@x),cast(CAST(@x as date) as datetime2)))

select @x, @GetDateMinutes

看起来是一个可能的解决方案。我会进行测试并回复答案。谢谢。 - Asaf Epelbaum

1

使用这里描述的技术截断秒数,避免所有字符串转换,然后进行比较。以下是一个完全包含了cross applyvalues的示例,用于封装开始和结束的截断逻辑:

-- truncate minutes from current date time
declare @currentDateTime datetime2(0) = DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), N'2018-10-01 23:58:32.912')), 0);

select @currentDateTime as CurrentDateTime
     , a.*
from (values -- create a table of dummy values
    (Convert(datetime2(3), N'2018-10-01 19:48:14.735'), Convert(datetime2(3), N'2018-10-10 02:00:00.000'))
  , (Convert(datetime2(3), N'2018-10-01 22:43:19.532'), Convert(datetime2(3), N'2018-11-01 12:17:26.663'))
) as a (StartDateTime, EndDateTime)
cross apply (values(
    -- truncate minutes from start date time
    DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), a.StartDateTime)), 0)
    -- truncate minutes from end date time
  , DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), a.EndDateTime)), 0)
)) as b (StartDateTimeWithoutSeconds, EndDateTimeWithoutSeconds)
where @currentDateTime between b.StartDateTimeWithoutSeconds and b.EndDateTimeWithoutSeconds;

您的数据似乎已经从开头和结尾截去了s/ms,但为了保持一致性,我会将同样的逻辑应用于所有涉及的值。以下是去除s/ms的公式,没有来自示例的"噪音":
DateAdd(minute, DateDiff(minute, 0, Convert(datetime2(0), <SomeDateTime>)), 0)

看起来是一个复杂但完整的解决方案。我会测试一下并回答您。谢谢。 - Asaf Epelbaum

1

SELECT Id FROM Table1 WHERE GETDATE() BETWEEN '2018-10-01 19:00:00' AND '2018-10-10 23:59:00'

查询Table1中在2018年10月1日19:00:00至2018年10月10日23:59:00之间的Id。

1
稍微解释一下为什么这个能够工作会让它更好。 - Sean Lange
@Radostina Zaykova 这将适用于字符串值。我有两列,因此如果使用BETWEEN子句,则查询将如下所示(这并没有显示我的问题的确切解决方案): SELECT Id FROM Table1 WHERE GETDATE() BETWEEN Start AND End - Asaf Epelbaum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接