我认为WHERE子句的项目顺序并不重要,为什么它在我的代码中很重要?

时间:2018-04-12 19:52:55

标签: sql-server tsql

这不起作用:

SELECT
    CAST(o.OrderNo AS INT) AS [OrderNo], 
    DATEADD(d, 7, CAST(SUBSTRING(o.User_Memo1, 
    CHARINDEX('Pack',o.User_Memo1)+5, 8) AS DATE)) AS [1 Week After Prod Due],
    o.User_Date1 AS [3 Week Ack Date]  
FROM Orders o 
    JOIN OrderDet od ON o.OrderNo = od.OrderNo
    LEFT JOIN DelTicket d ON o.OrderNo = d.OrderNo
WHERE CONVERT(VARCHAR(MAX), o.User_Memo1) IS NOT NULL
    AND o.User_Date1 IS NULL
    AND DATEADD(d, -24, DATEADD(d, 7, CAST(SUBSTRING(o.User_Memo1, 
    CHARINDEX('Pack',o.User_Memo1)+5, 8) AS DATE))) < CAST(GETDATE() AS DATE)
    AND SUBSTRING(o.User_Memo1, 1, 3) = 'Cut'
GROUP BY o.OrderNo, DATEADD(d, 7, CAST(SUBSTRING(o.User_Memo1, 
CHARINDEX('Pack',o.User_Memo1)+5, 8) AS DATE)), o.User_Date1, o.User_Date2, 
o.User_Number2, d.ShipDate, o.User_Number3
ORDER BY DATEADD(d, 7, CAST(SUBSTRING(o.User_Memo1, 
CHARINDEX('Pack',o.User_Memo1)+5, 8) AS DATE)) DESC;

我收到此错误:

  

从字符串转换日期和/或时间时转换失败。&gt;

如果我把这个项目:

    AND DATEADD(d, -24, DATEADD(d, 7, CAST(SUBSTRING(o.User_Memo1, 
CHARINDEX('Pack',o.User_Memo1)+5, 8) AS DATE))) < CAST(GETDATE() AS DATE)

在WHERE子句的末尾,它按预期运行完美。没有“剪切”的项目。在User_Memo1中确实应该无法转换。但是,我已经知道订单并不重要。所以我很困惑?

编辑:使用屏幕截图进行更新

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

理论上,顺序并不重要。但是,对于复杂查询,查询优化器可能会遵循不同的路径,并导致不同的执行计划。这对于具有多个连接的查询来说是典型的。更改连接顺序时,执行计划的形状可能会更改。我猜这可能是同一个问题。尝试检查两个选项的估计执行计划,看看它们是否有所不同......

当您将有问题的谓词放在WHERE子句的末尾时。执行计划是不同的(只有Microsoft知道原因),导致错误的有问题的行在转换之前被过滤掉。