【问题标题】:What is the optimal way to compare dates in Microsoft SQL server?在 Microsoft SQL Server 中比较日期的最佳方法是什么?
【发布时间】:2013-02-26 23:42:59
【问题描述】:

我在一个非常大的表中有一个 SQL datetime 字段。已编入索引,需要查询。

问题在于 SQL 总是存储时间组件(即使它总是午夜),但搜索的是当天,而不是时间。

declare @dateVar datetime = '2013-03-11;

select t.[DateColumn]
from MyTable t
where t.[DateColumn] = dateVar;

不会返回任何内容,因为 t.[DateColumn] 始终包含时间组件。

我的问题是最好的解决方法是什么?

似乎有两组主要的选项:

  1. 使用dateadd 创建第二个变量并使用between ... and>= ... and ... <=

  2. t.[DateColumn] 转换为仅限日期的组件 - 我认为这会导致所有索引都被忽略。

这两个看起来都非常混乱 - 我真的不想进行范围比较或扫描表格。

有没有更好的办法?

如果这些选项之一始终是最佳方式,那么如何以及为什么?

【问题讨论】:

    标签: sql sql-server tsql datetime query-optimization


    【解决方案1】:

    在任何情况下转换为DATE 或使用开放式日期范围都会产生最佳性能。仅供参考,使用索引转换为日期是表现最好的。更多测试不同技术的文章:What is the most efficient way to trim time from datetime? Aaron Bertrand 发布

    来自那篇文章:

    DECLARE @dateVar datetime = '19700204';
    
    -- Quickest when there is an index on t.[DateColumn], 
    -- because CONVERT can still use the index.
    SELECT t.[DateColumn]
    FROM MyTable t
    WHERE = CONVERT(DATE, t.[DateColumn]) = CONVERT(DATE, @dateVar);
    
    -- Quicker when there is no index on t.[DateColumn]
    DECLARE @dateEnd datetime = DATEADD(DAY, 1, @dateVar);
    SELECT t.[DateColumn] 
    FROM MyTable t
    WHERE t.[DateColumn] >= @dateVar AND 
          t.[DateColumn] < @dateEnd;
    

    同样来自那篇文章:使用BETWEENDATEDIFFCONVERT(CHAR(8)... 都比较慢。

    【讨论】:

      【解决方案2】:

      这是一个例子:

      我有一个 Order 表,其中包含一个名为 OrderDate 的 DateTime 字段。我想检索订单日期等于 01/01/2006 的所有订单。有以下方法可以做到:

      1) WHERE DateDiff(dd, OrderDate, '01/01/2006') = 0
      2) WHERE Convert(varchar(20), OrderDate, 101) = '01/01/2006'
      3) WHERE Year(OrderDate) = 2006 AND Month(OrderDate) = 1 and Day(OrderDate)=1
      4) WHERE OrderDate LIKE '01/01/2006%'
      5) WHERE OrderDate >= '01/01/2006'  AND OrderDate < '01/02/2006'
      

      已找到here

      【讨论】:

      • 在所有这些中,#1 被认为是最有效的:sqlservercentral.com/Forums/Topic937765-338-1.aspx
      • @RandomUs1r 选项#1 需要为表中的每一行运行datediff 计算,它肯定不会是最快或最有效的。选项 #2 与 varchar(20) 转换相同。选项 #4 和 #5 更有希望,我会再添加两个:6) where OrderDate between @dateVar and dateadd(day, 1, @dateVar) 和 7) WHERE convert(date, OrderDate) = @dateVar
      • 在这 5 种建议的方法中,1-4 都非常慢。 5 对于堆表来说很快,最快的方法(convert(date, OrderDate) 查看所选答案)甚至不在列表中。
      【解决方案3】:

      您可以添加一个仅包含日期而不包含时间的计算列。在这两个选项之间,我会选择 BETWEEN 运算符,因为它对我来说“更干净”,应该更好地利用索引。比较执行计划似乎表明BETWEEN 会更快;但是,在实际测试中,它们的表现是一样的。

      【讨论】:

      • @Keith +1 感谢您的链接。我知道大多数问题(我知道它具有包容性,并且我习惯性地在需要时为结束日期添加时间值),但最后几个问题对我来说是新的。在工作中,我们选择的所有时间值都被截断为分钟或秒(不,这不是我的决定。是的,缺乏精度很烦人。)所以纳秒问题还没有出现,但它们可能足够严重,我可能会提出将 BETWEEN 更改为 =&gt;...&lt; 的用法,以便今天与其他开发人员讨论。
      【解决方案4】:

      当日期在 fromdate 和 toDate 之间时获取项目。

      在哪里 convert(date, fromdate, 103) = '2016-07-26'

      【讨论】:

      • 嗨@gaze,欢迎来到 Stack Overflow。您的答案在这里并没有真正添加任何内容-如果您阅读了已接受的答案,您会发现他们已经涵盖了 convert 并解释了根据索引更改类型或使用是否更好,这确实是我要问的为了。要获得投票,您确实需要添加其他人没有添加的内容,或者先回答。
      猜你喜欢
      • 2012-03-07
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 2012-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多