[英]How do I force an OR clause over another in a WHERE clause in a query in SQL Server?
我有一个很大的查询,在WHERE子句中,我有类似以下内容:
做一点事
要么
做其他事情
(仅1个OR)...
现在,如果我运行此查询,SQL大约需要13秒才能完成。
如果删除OR子句的第二部分,查询将非常快速地运行。
SQL是否不应该执行OR的第一部分,如果为true,则不要通过不查看OR的另一部分来完成查询?
为什么SQL会同时查看OR的两端? 为什么不从第一个开始?
如果删除OR子句的第二部分,查询将运行得非常快。
有人可以给我一些如何实现此目标的提示吗?
编辑-这是查询:
SELECT msc.ID,
msc.MediaCompanyID,
msc.AiringNumber,
msc.ClientNumber,
cl.ClientName,
MediaCompanyName,
CONVERT(VARCHAR, StandardDate, 101) StandardDateOnly,
CONVERT(DATETIME, CONVERT(VARCHAR, StandardDate, 101)) StandardDateOnlyDateType,
CONVERT(VARCHAR, StandardDate, 101) + ' ' + CONVERT(VARCHAR, StandardDate, 108) StandardDate,
CONVERT(VARCHAR, BroadcastDate, 101) + ' ' + CONVERT(VARCHAR, BroadcastDate, 108) BroadCastDate,
Station,
StationID,
msc.MediaCodeID,
msc.MediaCode,
MediaCodeDescr,
PhoneNumber,
DMA = CASE WHEN DMA IS NULL THEN MarketType
ELSE DMA
END,
msc.MarketID,
m.MarketDescr,
MIN(GrossCost) GrossCost,
MIN(ClientCost) ClientCost,
msc.CountryID,
CASE CountryName
WHEN 'UNITED STATES' THEN 'USA'
ELSE CountryName
END AS CountryName,
msc.LanguageID,
l.Language,
CASE IsConfirmed
WHEN 0 THEN 'No'
WHEN 1 THEN 'Yes'
END AS Teletrax
FROM dbo.MediaScheduleComplete msc
JOIN TVTraffic.dbo.Country c
ON msc.CountryID = c.CountryId
JOIN TVTraffic.dbo.Language l
ON msc.LanguageID = l.LanguageID
JOIN TVTraffic.dbo.Client cl
ON msc.ClientNumber = cl.ClientNumber
JOIN dbo.MediaCode mc
ON msc.MediaCodeID = mc.MediaCodeID
JOIN dbo.Market m
ON msc.MarketID = m.MarketID
LEFT JOIN TVTraffic.dbo.Offer o
ON mc.OfferID = o.OfferID
INNER JOIN @temp n
ON n.i = msc.ID
WHERE (
@MediaScheduleCompleteIDs IS NOT NULL
AND msc.ID IN (SELECT i
FROM TVTraffic.dbo.ufnListToSelectInt(@MediaScheduleCompleteIDs))
)
OR (
@MediaScheduleCompleteIDs IS NULL
AND (
StandardDate BETWEEN @from AND @to
AND (
msc.MediaCompanyID = @mediaCompanyID
OR @mediaCompanyID = 255
)
AND (
MarketType = @MarketType
OR @MarketType = ''
)
AND (
msc.ClientNumber = @clientID
OR @clientID = 0
)
-- and MediaCodeTypeID in (1,2,@SpecialTypeID)
AND (
msc.MediaCodeTypeID = @mediaCodeTypeID
OR @mediaCodeTypeID = 0
)
AND (
msc.CountryID = @CountryID
OR @CountryID = 0
)
AND (
msc.LanguageID = @LanguageID
OR @LanguageID = 0
)
AND (
mc.OfferID = @OfferID
OR @OfferID = 0
)
)
)
GROUP BY msc.ID,
msc.MediaCompanyID,
msc.AiringNumber,
msc.ClientNumber,
cl.ClientName,
MediaCompanyName,
StandardDate,
BroadcastDate,
Station,
StationID,
msc.MediaCodeID,
msc.MediaCode,
MediaCodeDescr,
PhoneNumber,
DMA,
msc.MarketID,
MarketDescr,
MarketType,
msc.CountryID,
CASE CountryName
WHEN 'UNITED STATES' THEN 'USA'
ELSE CountryName
END,
msc.LanguageID,
l.Language,
CASE IsConfirmed
WHEN 0 THEN 'No'
WHEN 1 THEN 'Yes'
END
ORDER BY ClientCost DESC,
StandardDate ASC
在SQL的WHERE中,OR并非短路,因为它不是布尔运算。 搜索条件可以过滤掉行,以便它可以返回满足任一侧的所有行。
因此,自然地,您必须在OR的两侧找到所有行才能返回它们。
所以当你有类似的东西:
SELECT QUERY WHERE
[search condition 1] OR [search condition 2]
您将始终必须找到满足搜索条件1 或搜索条件2的所有行,并将它们作为结果集返回。
现在,如果您执行以下操作:
IF (1 = 1) OR ( 1 / 0 = 0)
PRINT 1
ELSE
PRINT 2
您会看到IF需要布尔结果语句,因此可以在某些类型的布尔检查中使用短路(2012年及以后可用,可能不完全向后兼容)
要补充另一个答案,SQL引擎的工作方式是它需要构建优化的执行计划,然后执行它们。 为此,它评估每个表达式,然后确定执行步骤。 这属于编译中。 仅当您使用动态SQL时,才会对查询进行即时评估。 但是即使如此,在使用OR
语句的情况下,Allan的回答也可以很好地解释这一点。
检查此文本http://sommarskog.se/dyn-search-2008.html
尝试在查询末尾添加OPTION(RECOMPILE)。 如文章中所述,我猜查询优化器正在重用不适合测试的查询计划。 这样,每次调用sp时,都会重新计算查询计划,因此它会随参数值的变化而变化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.