【问题标题】:Datediff in where clause在 where 子句中的 Datediff
【发布时间】:2014-10-15 13:28:43
【问题描述】:

我正在尝试在我的 SQL 存储过程的 WHERE 子句中使用 Datediff/DateAdd 函数。除了其他主查询,我的查询包含 2 个日期列和 1 个主列:-

WHERE DATE1 BETWEEN @MonthStart AND @MonthEnd 
  AND "MAINCOLUMN" IS NOT NULL 
  OR  "DATE2" <= DATEADD(MM, -36,GETDATE()) AND "MAINCOLUMN" IS NOT NULL

我想返回MainColumn Date1 位于@MonthStart@MonthEnd 之间的那些行

或者

MainColumn 的 Date2 列 DATE 在过去 36 个月之间(从今天的日期到过去 3 年的日期)

我什至尝试过:

WHERE "DATE1" BETWEEN @MonthStart AND @MonthEnd 
  AND "MAINCOLUMN" IS NOT NULL 
  OR  "DATE2" BETWEEN DATEDIFF(MM, -36, GETDATE()) AND GETDATE() 
  AND "MAINCOLUMN" IS NOT NULL

还有:

WHERE "DATE1" BETWEEN @MonthStart AND @MonthEnd 
  AND "MAINCOLUMN" IS NOT NULL 
  OR  DATEDIFF(MM, DATE2, GETDATE()) <= 36 AND "MAINCOLUMN" IS NOT NULL

问题是,一切都在运行,但它们需要很长时间才能运行。在 WHERE 子句中添加 OR 语句之前,我的报告几乎不需要 4-5 分钟即可运行,尽管它有近 200,000 行但是在添加了OR 语句之后,它就一直在继续。

【问题讨论】:

  • 您需要检查执行计划。我猜想在您添加第二个条件之前,它可能已经能够使用Date1 上的索引,但现在它可能已被强制执行表扫描。
  • 是的,我在提问之前也这样做了,但是我的查询非常复杂,所以基本上这对我没有帮助:(

标签: sql sql-server sql-server-2005 sql-server-2012


【解决方案1】:

帕拉西西斯!在这两种情况下,MainColumn 必须为非空。您可以像这样简化WHERE 子句:

WHERE MainColumn IS NOT NULL
AND (DATE1 BETWEEN @MonthStart AND @MonthEnd OR DATE2 <= DATEADD(MM, -36,GETDATE()))

【讨论】:

  • 非常感谢.. 这个帮助了我.. 运行报告大约需要 7 到 8 分钟,这仍然可以,因为记录数量已增加到 400,000 多条。
【解决方案2】:

这可能会帮助你...

CREATE TABLE data
    (
     id uniqueidentifier primary key, 
     MainColumn varchar(20), 
     date1 datetime,
     date2 datetime
    );



declare @MonthStart int;
Declare @MonthEnd int;
set @MonthStart = 4;
set @MonthEnd = 8;
Select * from data WHERE DATE1 BETWEEN @MonthStart AND @MonthEnd 
  AND MAINCOLUMN IS NOT NULL 
  OR  DATE2 <= DATEADD(MM, -36,GETDATE()) AND data.MainColumn IS NOT NULL

【讨论】:

  • 只是想知道.. 为什么将 MonthStart 和 MonthEnd 声明为 int 以及为什么它们被初始化为 4 和 8? MonthStart 和 MonthEnd 是我报告中的过滤器,作为用户在运行时输入的日期范围。
  • 我声明它们只是为了保留您原始查询的文本...您将它们作为参数提供给我想象的命令对象...
【解决方案3】:

您需要确保您的逻辑分组正确。试试:

`WHERE 
(
 "DATE1" BETWEEN @MonthStart AND @MonthEnd
 AND "MAINCOLUMN" IS NOT NULL
) OR (
 DATEDIFF(MM, DATE2, GETDATE()) <= 36
 AND "MAINCOLUMN" IS NOT NULL
)`

我将 OR 两侧的部分用括号括起来,以确保如果任一块为真,它将触发。

【讨论】:

  • 虽然这很清楚,但它不应该成为问题,因为 AND 的优先级高于 OR。无论如何也解决不了问题。
  • 我刚刚尝试分组并再次运行查询.. 看看需要多长时间:(
猜你喜欢
  • 1970-01-01
  • 2017-06-29
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-07
  • 1970-01-01
相关资源
最近更新 更多