这是一个查询。 Where
子句包含两部分,它们都是假的(因为@Notify不等于13005或13105)。
但是这个查询返回36行。如果block包含false,它如何返回任何内容? CHECKDB显示没有错误,重启也没有帮助。如果我添加1 = 0条件而不是@Notify = 13005,则查询返回0行。
SQL SERVER版本 - Microsoft SQL Server 2008(RTM) - 10.0.1600.22 (英特尔X86) 2008年7月9日14:43:34 版权所有(c)1988-2008 Microsoft Corporation 在Windows NT 6.1(Build 7601:Service Pack 1)上使用高级服务的Express Edition(WOW64)
declare @Notify smallint
set @Notify = 20
select distinct DMD_ID
,cast(DMD_Document as varchar) + '-' + cast(Cl_Place as varchar) as DMD_Document
,DMD_Client
from DocMoveDemand
inner join Client on DMD_Client = Cl_ID
inner join DocMoveDemandList on DMDL_SDoc = DMD_ID
left outer join DocOut on DO_DocMoveDemand = DMD_ID
where (
@Notify = 13005
and DMDL_DocMoveDenyReason in (2,3,4)
and (
DO_IsMove = 'Y'
or DMD_IsReturn = 1
)
and DateDiff(DD, isnull(DMD_DateReturn, DO_DateMove), GETDATE()) < 14
and DMD_NotifyInv1 = 0
)
or (
@Notify = 13105
and DMDL_DocMoveDenyReason in (2,3,4)
and (
DO_IsMove = 'Y'
or DMD_IsReturn = 1
)
and DateDiff(DD, isnull(DMD_DateReturn, DO_DateMove), GETDATE()) >= 14
and DMD_NotifyInv2 = 0
)
order by DMD_ID
以下是直接比较https://www.brentozar.com/pastetheplan/?id=S1hTRr59W和(SELECT @Notify)
https://www.brentozar.com/pastetheplan/?id=Hk27lI9cW
答案 0 :(得分:3)
我同意这看起来像查询优化器错误(specifically this one)fixed in CU2( FIX:如果直通谓词与其查询中的过滤器一起使用,则查询可能会返回错误的结果计划)。对WHERE
谓词的此位的评估被错误地推送到针对DocOut
的键查找中,并且不针对与DocOut
中的任何内容不匹配且由外部联接保留的行进行评估
下面的查找运算符(编号为4)具有
的搜索谓词Seek Keys[1]: Prefix: [SMNikopol].[dbo].[DocOut].DO_ID
= Scalar Operator([SMNikopol].[dbo].[DocOut].[DO_ID])
和
的残差谓词( [SMNikopol].[dbo].[DocOut].[DO_IsMove] = 'Y'
OR [SMNikopol].[dbo].[DocMoveDemand].[DMD_IsReturn] = ( 1 ) )
AND ( [@Notify] = ( 13005 )
AND datediff(day, CONVERT_IMPLICIT(datetime, isnull([SMNikopol].[dbo].[DocMoveDemand].[DMD_DateReturn], [SMNikopol].[dbo].[DocOut].[DO_DateMove]), 0), getdate()) < ( 14 )
AND [SMNikopol].[dbo].[DocMoveDemand].[DMD_NotifyInv1] = ( 0 )
OR [@Notify] = ( 13105 )
AND datediff(day, CONVERT_IMPLICIT(datetime, isnull([SMNikopol].[dbo].[DocMoveDemand].[DMD_DateReturn], [SMNikopol].[dbo].[DocOut].[DO_DateMove]), 0), getdate()) >= ( 14 )
AND [SMNikopol].[dbo].[DocMoveDemand].[DMD_NotifyInv2] = ( 0 ) )
DocOut
IsBaseRow1010
的系统生成列以及表中的ID列。IsBaseRow1010 IS NULL
上有一个遍历谓词,这意味着对于外部联接未能找到匹配项的行,将跳过密钥查找。IsBaseRow1010 IS NULL
永远不会获得评估的谓词,并最终作为结果输出。当您将查询文本更改为(select @Notify) = 13005
等时,OR
将被表示为半连接,对应于应用了过滤器的两个一行虚拟表中的UNION ALL
,而不是查找的残差谓词,因此可以避免错误。
答案 1 :(得分:1)
用(SELECT @Notify)查询返回0条记录
根据您的版本SQL SERVER 2008 Express Edition with Advanced Services
,我猜这是一个错误。直接比较不起作用
@Notify = 13005
但是
(SELECT @Notify) = 13005
表现得如此。
我也会尝试: