简体   繁体   English

如何在SQL Server查询的WHERE子句中强制OR子句在另一个子句上?

[英]How do I force an OR clause over another in a WHERE clause in a query in SQL Server?

I have a big query and in the WHERE clause I have something like: 我有一个很大的查询,在WHERE子句中,我有类似以下内容:

Do something 做一点事

OR 要么

Do something else 做其他事情

(only 1 OR)... (仅1个OR)...

Right now if I run this query, SQL is taking about 13 seconds to finish. 现在,如果我运行此查询,SQL大约需要13秒才能完成。

If I remove the second part of the OR clause, the query runs VERY fast. 如果删除OR子句的第二部分,查询将非常快速地运行。

Shouldn't SQL execute the first part of the OR and, if true, finish the query by NOT looking at the other part of the OR? SQL是否不应该执行OR的第一部分,如果为true,则不要通过不查看OR的另一部分来完成查询?

Why is SQL looking at both sides of the OR? 为什么SQL会同时查看OR的两端? Why does it not start with the first one? 为什么不从第一个开始?

If I remove the second part of the OR clause, the query runs very fast. 如果删除OR子句的第二部分,查询将运行得非常快。

Can someone give me some tips on how to make this happen? 有人可以给我一些如何实现此目标的提示吗?

EDIT - here's the query: 编辑-这是查询:

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

OR is not short circuiting in WHERE in SQL because it's not a boolean operation. 在SQL的WHERE中,OR并非短路,因为它不是布尔运算。 It's search conditions to filter out rows so it can return all rows which fulfil either side. 搜索条件可以过滤掉行,以便它可以返回满足任一侧的所有行。
So naturally you'll have to find all rows on both sides of the OR to be able to return them. 因此,自然地,您必须在OR的两侧找到所有行才能返回它们。

So when you have something like: 所以当你有类似的东西:

SELECT QUERY WHERE
[search condition 1] OR [search condition 2]

You will always have to find all rows which fulfil search condition 1 OR search condition 2 and return them as the result set. 您将始终必须找到满足搜索条件1 搜索条件2的所有行,并将它们作为结果集返回。

Now if you did something like the following: 现在,如果您执行以下操作:

IF (1 = 1) OR ( 1 / 0 = 0)
 PRINT 1
ELSE 
 PRINT 2

You will see that the IF requires a boolean resulted statement and therefore can shortcircut on some types of boolean checks (works in 2012 and onwards, may not be completely backwards compatibility) 您会看到IF需要布尔结果语句,因此可以在某些类型的布尔检查中使用短路(2012年及以后可用,可能不完全向后兼容)

To add on to the other answer, how SQL engine works is that it needs to build an optimized execution plan, which is them followed by it. 要补充另一个答案,SQL引擎的工作方式是它需要构建优化的执行计划,然后执行它们。 For this, it evaluates every expression and then decides the steps of execution. 为此,它评估每个表达式,然后确定执行步骤。 This falls under compilation. 这属于编译中。 Only if you use dynamic SQL, will the query be evaluated on the fly. 仅当您使用动态SQL时,才会对查询进行即时评估。 But even then, in case of OR statement, it's a different story which is well explained by Allan's answer. 但是即使如此,在使用OR语句的情况下,Allan的回答也可以很好地解释这一点。

Check this text http://sommarskog.se/dyn-search-2008.html 检查此文本http://sommarskog.se/dyn-search-2008.html

Try adding OPTION(RECOMPILE) at the end of the query. 尝试在查询末尾添加OPTION(RECOMPILE)。 As explained in the article, I guess the query optimizer is reusing a query plan that is not suited for the test your making. 如文章中所述,我猜查询优化器正在重用不适合测试的查询计划。 That way every time you call the sp the query plan will be recalculated so it will vary with the values of the parameters. 这样,每次调用sp时,都会重新计算查询计划,因此它会随参数值的变化而变化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Where子句基于SQL Server中的另一个查询 - Where clause based on another query in SQL Server 如何编写一个SQL查询,其where子句包含在另一个查询中? - How do I write an SQL query whose where clause is contained in another query? 如何在SQL Developer的查询的WHERE子句中使用unicode? - How do I use unicode in the WHERE clause of a query in SQL Developer? 如何在SQL查询where子句中指定多个值? - How do I specify multiple values in SQL query where clause? 如何在参数化 SQL 查询中使用多个 WHERE 子句? - How do I use multiple WHERE clause in parameterized SQL query? 如何计算 SQL 服务器中带有 where 子句的行数? - How do I count the rows with a where clause in SQL Server? 使用一个查询的输出作为另一个查询的WHERE子句— SQL Server 2008 - Using output of one query as WHERE clause of another — SQL Server 2008 我可以忽略另一个SQL查询中的where子句吗 - Can I ignore a where clause in another sql query 我怎么知道一个子句查询结果包含另一个子句查询结果? - How can I know a where-clause query results contains another where-clause query results? 如何将 SQL 查询的结果用于另一个查询的 WHERE 子句? - How can I use an SQL query's result for the WHERE clause of another query?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM