【问题标题】:Best way to compare dates without time in SQL Server在 SQL Server 中比较没有时间的日期的最佳方法
【发布时间】:2012-03-07 16:40:46
【问题描述】:
select * from sampleTable 
where CONVERT(VARCHAR(20),DateCreated,101) 
=     CONVERT(VARCHAR(20),CAST('Feb 15 2012  7:00:00:000PM' AS DATETIME),101)

我想比较没有时间的日期

上面的查询可以吗?或您建议的其他更好的解决方案

  • 我使用的是 SQL Server 2005
  • 在服务器上以 UTC 格式保存的日期
  • 针对此数据的用户属于不同的时区

【问题讨论】:

标签: sql sql-server datetime utc


【解决方案1】:

声明@DateToday Date='2019-10-1'; 打印@DateToday;

打印 Abs(datediff(day, @DateToday,CAST('oct 1 2019 7:00:00:000PM' AS DATETIME)))

这是比较 3 天的时间。

我在 SQL Server 2014 上对此进行了测试,它可以工作。

【讨论】:

    【解决方案2】:

    不要使用转换 - 无缘无故地涉及字符串。一个技巧是日期时间实际上是一个数字,而天是整数部分(时间是小数部分);因此这一天是价值的FLOOR:这只是数学,而不是字符串 - 快得多

    declare @when datetime = GETUTCDATE()
    select @when -- date + time
    declare @day datetime = CAST(FLOOR(CAST(@when as float)) as datetime)
    select @day -- date only
    

    在您的情况下,无需转换回日期时间;并且使用范围可以进行最有效的比较(尤其是索引时):

    declare @when datetime = 'Feb 15 2012  7:00:00:000PM'
    declare @min datetime = FLOOR(CAST(@when as float))
    declare @max datetime = DATEADD(day, 1, @min)
    
    select * from sampleTable where DateCreated >= @min and DateCreated < @max
    

    【讨论】:

    • 经过测试,最好保留在datetime域中stackoverflow.com/a/1177529/27535
    • @gbn 有趣。不过,两者之间的距离非常接近。关键点:不要使用字符串;p
    • 我也更喜欢保持在 datetime 内(而不是强制转换为 float),因为我更喜欢将 datetime 的数字表示视为实现细节(即,days 是 datetime 的整数部分)。
    【解决方案3】:

    简单转换为Date 将解决问题。

    DECLARE @Date datetime = '04/01/2016 12:01:31'
    
    DECLARE @Date2 datetime = '04/01/2016'
    
    SELECT CAST(@Date as date)
    
    SELECT CASE When (CAST(@Date as date) = CAST(@Date2 as date)) Then 1 Else 0 End
    

    【讨论】:

      【解决方案4】:
      SELECT .......
      FROM ........
      WHERE 
      CAST(@DATETIMEVALUE1 as DATE) = CAST(@DATETIMEVALUE2 as DATE)
      

      缺点是您正在投射过滤器列。

      如果过滤列上有索引,那么,由于您正在转换,SQL 引擎不能再使用索引来更有效地过滤日期。

      【讨论】:

        【解决方案5】:

        说明

        不要将您的 Date 转换为 varchar 并进行比较,因为字符串比较不快。

        如果您使用&gt;=&lt; 过滤您的DateCreated 列,速度会快得多。

        如果您没有参数(如示例中的字符串),则应使用 ISO 格式 &lt;Year&gt;&lt;Month&gt;&lt;Day&gt;

        样本

        根据您的样本

        DECLARE @startDate DateTime
        DECLARE @endDate DateTime
        
        SET @startDate = '20120215'
        SET @endDate = DATEADD(d,1,@startDate)
        
        SELECT * FROM sampleTable 
        WHERE DateCreated >= @startDate AND DateCreated < @endDate
        

        更多信息

        【讨论】:

        • minor: re the where construction - 它需要测试,但我期望一个明显的基于范围的方法 (&gt;= @min and &lt; @max) 可以更好地工作,特别是对于索引数据。
        • @MarcGravell 我认为如果他想要两个日期之间的数据但他只想要一天的数据是有道理的。不是吗?
        • 范围可以正好是一天,很简单;但它应该允许直接使用索引,而不必对每行进行任何计算。
        • 啊,不:读取是相同的 - 但第二个 CPU 更高:pastie.org/3393454 - 意思是:范围方法更有效
        • 对于那些喜欢性能的人来说,根据我的测试,我的解决方案更快
        【解决方案6】:

        使用 112 CONVERT 的格式

        select * 
        from sampleTable 
        where 
          CONVERT(VARCHAR(20),DateCreated,112) 
        =     CONVERT(VARCHAR(20),CAST('Feb 15 2012  7:00:00:000PM' AS DATETIME),112)
        

        如果您的 sql server 版本 2008+ 使用 DATE 类型

        select * from sampleTable 
        where CONVERT(DATE,DateCreated) 
        =     CONVERT(DATE,CAST('Feb 15 2012  7:00:00:000PM' AS DATETIME))
        

        【讨论】:

          【解决方案7】:
          select * from sampleTable 
          where date_created ='20120215'
          

          这也会将您的列与特定日期进行比较 不考虑时间

          【讨论】:

          • 转换为 varchars 然后比较比比较日期要慢
          • 这行不通。 OP 想要给定日期的所有行,而不仅仅是 2012-02-15 00:00.000 数据。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-02-26
          • 2019-12-06
          • 2012-06-02
          • 1970-01-01
          • 2018-07-29
          • 1970-01-01
          • 2021-04-22
          相关资源
          最近更新 更多