【问题标题】:SQL Server - Check if given date+time is between two datetime variables by exact date+timeSQL Server - 通过确切的日期+时间检查给定的日期+时间是否在两个日期时间变量之间
【发布时间】:2018-10-11 16:40:51
【问题描述】:

我在数据库表中有两个日期时间列:@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。我的代码将此类日期视为不符合给定范围。但我不在乎 s/ms。

有解决办法吗?

更新:

我想要达到的精确度分钟。所以我什至不需要考虑秒数和毫秒数。我将使用的日期时间格式是“yyyy-MM-dd hh-mm”,但我不知道如何使用 BETWEEN 子句将 Start 和 End 转换为所示格式,以便比较日期。

【问题讨论】:

  • 您的代码应该可以在任何版本的 SQL Server 中工作。
  • 如果 getdate() 完全 2018-10-10 23:59:00 到最后一个毫秒会怎样?
  • 这里 在您的查询中 - GetDate() 始终返回当前日期时间。但是为了从您的表中获取记录,请使用您的表列而不是 GetDate()
  • Between 真的很糟糕,尤其是在日期时间检查方面。这是关于该主题的精彩讨论。 sqlblog.org/2011/10/19/…
  • @asaf 你的查询很完美。唯一可能的问题是当变量的数据类型是datetime 并且您尝试推送一个毫秒值,例如00:00:00.00100:00:00.002。这些值会四舍五入,最终得到00:00:00.00000:00:00.003

标签: sql sql-server datetime


【解决方案1】:

你似乎想要这个逻辑:

WHERE GETDATE() >= Start
  AND GETDATE() < DATEADD(minute, 1, End)

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

【讨论】:

  • 我采纳了你的建议,它奏效了!非常感谢!毕竟 BETWEEN 解决方案似乎也有效。
【解决方案2】:

在“2018-10-01 19:00:00”和“2018-10-10 23:59:00”之间从表 1 中选择 ID

【讨论】:

  • 稍微解释一下为什么这样会更好。
  • @Radostina Zaykova 这适用于字符串值。我有两列,因此在使用 BETWEEN 子句的情况下查询看起来像这样(它没有显示我的问题的确切解决方案):SELECT Id FROM Table1 WHERE GETDATE() BETWEEN Start AND End
【解决方案3】:

试试

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

【讨论】:

  • 似乎是一个可能的解决方案。我将对其进行测试并返回答案。谢谢
【解决方案4】:

使用技术described here 截断秒数以避免所有字符串转换,然后进行比较。这是一个完整的示例,它使用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)

【讨论】:

  • 似乎是一个复杂但完整的解决方案。我将对其进行测试并返回答案。谢谢
猜你喜欢
  • 2018-07-26
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 2012-05-27
  • 2013-03-01
  • 2017-04-22
相关资源
最近更新 更多