什么原因导致在T-SQL中忽略WHERE子句?

时间:2016-12-22 21:30:44

标签: sql sql-server

我之前遇到过这个问题,但从未真正弄清楚问题是什么。我希望你们中的一位大师帮助解释什么会导致WHERE子句被忽略。大图片问题是:

当忽略WHERE子句时,哪里是开始寻找的最佳位置?

通常会导致此问题的原因是什么?

在这种特定情况下,我尝试过滤掉某些服务代码。我尝试过使用NOT LIKE子句,或者只是使用IN()子句将我想要的服务代码列入白名单,但无论如何都要完全忽略该语句。每个服务代码也与服务类相关联,并使用这些相同的运算符来过滤掉所需的服务类或将其列入白名单。我已经尝试将NOT LIKE和IN子句移动到我的WHERE下的第一个标准,如果它是一个操作顺序问题,并且我在某处检查了缺失的括号。因此,此查询返回的结果没有任何错误消息,但它不会过滤掉不需要的行。

查询很乱,因为每个发票都有5个不同的字段,TechID可以在其中,每个字段表示不同的字段,但这里是查询:

{{1}}

非常感谢任何建议或咨询。谢谢!

4 个答案:

答案 0 :(得分:1)

没有任何情况会导致整个where子句被忽略。可能发生的事情是你的where子句在OR的任一侧有表达式,如果一方评估为true,那么另一方并不重要。当你将许多AND和OR组合在一起时,你必须非常小心你的括号。

答案 1 :(得分:1)

以下是您的查询的重新格式,我已经标记了我认为您的or出现故障的位置。

select 
  Location = (select LocationCode 
              from Locations 
              where Invoices.Locationid = Locations.Locationid)
 , Invoices.OrderNum
 , Invoices.ServiceCode
 , Invoices.WorkDate
 , Invoices.Total
 /* , ServiceClass = Classes.Code */
 , Tech   = (select Employees.Username 
             from Employees 
             where Employees.TechId = Invoices.Techid1)
 , Helper = (select Employees.Username
             from Employees
             where Employees.TechId = Invoices.Techid2)
 , 'Sales Blue 1' = (select Employees.Username
                     from Employees
                     where Employees.TechId = Invoices.Techid3)
 , 'Sales Blue 2' = (select Employees.Username
                     from Employees
                     where Employees.TechId = Invoices.Techid4)
 , 'Term Self'    = (select Employees.Username
                     from Employees
                     where Employees.TechId = Invoices.Techid5)
 , 'Sales Rep' = case 
   when /* self Gen */ Invoices.Techid5 in ('298', '194', '330', '391', '335') 
     then (
       select Employees.Username
       from Employees
       where Employees.TechId = Invoices.Techid5) 
   when /* Sales Blue 2 */ Invoices.Techid4 in ('298', '194', '330', '391', '335') 
    then (
      select Employees.Username
      from Employees
      where Employees.TechId = Invoices.Techid4) 
   when /* Sales Blue 1 */ Invoices.Techid3 in ('298', '194', '330', '391', '335') 
    then (
      select Employees.Username
      from Employees
      where Employees.TechId = Invoices.Techid3) 
   end 
 , Sale status = case 
      when /* self Gen */ Invoices.Techid5 in ('298', '194', '330', '391', '335') 
        then 'Self-Gen' 
      when /* Sales Blue 2 */ Invoices.Techid4 in ('298', '194', '330', '391', '335') 
        then 'bsp Lead 2' 
      when /* Sales Blue 1 */ Invoices.Techid3 in ('298', '194', '330', '391', '335') 
        then 'bsp Lead' 
        else 'Error' 
        end
from Employees Employees 
  inner join Invoices Invoices on Employees.Techid = Invoices.Techid3
  inner join Services Services on Invoices.ServiceCode = Services.Code
  inner join Classes Classes on Services.Classid = Classes.Classid
where /* Brian is 298, Cindy is 194, Jeremiah is 330, Monty is 391, and Tom is 335. */ 
 /* Technician and Sales Rep */ 
  Invoices.ServiceCode in ('bed bug chem co', 'bed bug chem')
  and (
        Invoices.Techid1 in ('298', '194', '330', '391', '335')
    and Invoices.Techid3 in ('298', '194', '330', '391', '335')
     or Invoices.Techid5 in ('298', '194', '330', '391', '335')  
    )   /* Sales Blue 1 , Sold but bspc Lead */ 

/* ----------------------------------------------- */    
/* do these 'or's belong somewhere else? */
  or Invoices.Techid3 in ('298', '194', '330', '391', '335')   /* Sales Blue 2 */ 
  or Invoices.Techid4 in ('298', '194', '330', '391', '335')    /* Term self (Gen) */ 
  or Invoices.Techid5 in ('298', '194', '330', '391', '335')
/* ----------------------------------------------- */
  and (
      Invoices.WorkDate <= GetDate()
        and year(Invoices.WorkDate) = year(GetDate())
    )
  and Invoices.ServiceCode not like 'eom%'
  and Invoices.ServiceCode not like 'eom1%'
  and Invoices.ServiceCode not like 'M_%'
  and Invoices.ServiceCode not like 'M1%'
  and Invoices.ServiceCode not like 'Q_%'
  and Invoices.ServiceCode not like 'Q1__%'
/* and Classes.Code not in ('eom', 'quarterly', 'monthly') */
order by Sales Rep, Sale status

答案 2 :(得分:0)

试试这个:

SELECT
    Locations.LocationCode AS [Location],
    Invoices.OrderNum,
    Invoices.ServiceCode,
    Invoices.WorkDate,
    Invoices.Total,
--  Classes.Code AS ServiceClass,
    Tech.Username AS Tech,
    Helper.Username AS Helper,
    SB1.Username AS [Sales Blue 1],
    SB2.Username AS [Sales Blue 2],
    TS.Username AS [Term Self],
    CASE
        WHEN --Self Gen
        Invoices.TechID5 IN (
            298,194,330,391,335) 
        THEN TS.Username
    ELSE 
        CASE WHEN --Sales Blue 2
            Invoices.TechID4 IN (
                298,194,330,391,335) 
            THEN SB2.Username
        ELSE
            CASE WHEN --Sales Blue 1
                Invoices.TechID3 IN (
                    298,194,330,391,335) 
                THEN SB1.Username
            END 
        END
    END
    AS [Sales Rep],
     CASE WHEN --Self Gen
        Invoices.TechID5 IN (
            298,194,330,391,335) 
        THEN 'Self-Gen'
    ELSE
        CASE WHEN --Sales Blue 2
            Invoices.TechID4 IN (
                298,194,330,391,335) 
            THEN 'BSP Lead 2'
        ELSE
            CASE WHEN --Sales Blue 1
                Invoices.TechID3 IN (
                    298,194,330,391,335)
                THEN 'BSP Lead'
                ELSE 'Error'
            END
        END
    END AS [Sale Status]
FROM Employees 
    INNER JOIN Invoices 
        ON Employees.TechID = Invoices.TechID3
    INNER JOIN [Services] 
        ON Invoices.ServiceCode = [Services].Code
    INNER JOIN Classes
        ON [Services].ClassID = Classes.ClassID
    INNER JOIN Locations
        ON Invoices.LocationID = Locations.LocationID
    -- Brian is 298, Cindy is 194, Jeremiah is 330, Monty is 391, and Tom is 335.
    -- Technician AND Sales Rep
    INNER JOIN Employees Tech
        ON Tech.TechID = Invoices.TechID1
    INNER JOIN Employees Helper
        ON Helper.TechID = Invoices.TechID2
    INNER JOIN Employees SB1
        ON SB1.TechID = Invoices.TechID3
    INNER JOIN Employees SB2
        ON SB2.TechID = Invoices.TechID4
    INNER JOIN Employees TS
        ON TS.TechID = Invoices.TechID5
WHERE
    Invoices.ServiceCode IN (
        'BED BUG CHEM CO',
        'BED BUG CHEM'
        )
    AND Invoices.WorkDate <= GetDate()
    AND YEAR (Invoices.WorkDate) = YEAR (GetDate())
    AND Invoices.ServiceCode NOT LIKE 'EOM%'
    AND Invoices.ServiceCode NOT LIKE 'EOM1%'
    AND Invoices.ServiceCode NOT LIKE 'M_%'
    AND Invoices.ServiceCode NOT LIKE 'M1%'
    AND Invoices.ServiceCode NOT LIKE 'Q_%'
    AND Invoices.ServiceCode NOT LIKE 'Q1__%'
    /* AND Classes.Code NOT IN ('EOM', 'QUARTERLY', 'MONTHLY') */
    ORDER BY
        CASE
            WHEN --Self Gen
            Invoices.TechID5 IN (
                298,194,330,391,335) 
            THEN TS.Username
        ELSE 
            CASE WHEN --Sales Blue 2
                Invoices.TechID4 IN (
                    298,194,330,391,335) 
                THEN SB2.Username
            ELSE
                CASE WHEN --Sales Blue 1
                    Invoices.TechID3 IN (
                        298,194,330,391,335) 
                    THEN SB1.Username
                END 
            END
        END,
         CASE WHEN --Self Gen
            Invoices.TechID5 IN (
                298,194,330,391,335) 
            THEN 'Self-Gen'
        ELSE
            CASE WHEN --Sales Blue 2
                Invoices.TechID4 IN (
                    298,194,330,391,335) 
                THEN 'BSP Lead 2'
            ELSE
                CASE WHEN --Sales Blue 1
                    Invoices.TechID3 IN (
                        298,194,330,391,335)
                    THEN 'BSP Lead'
                    ELSE 'Error'
                END
            END
        END ;

答案 3 :(得分:0)

可能问题在于您的操作顺序,因为在同一查询中使用and和Or时没有正确使用括号。让我分解你的查询的一小部分,你可以看到我的意思

WHERE
    -- Brian is 298, Cindy is 194, Jeremiah is 330, Monty is 391, and Tom is 335.
    -- Technician AND Sales Rep
    "Invoices"."ServiceCode" IN ( 'BED BUG CHEM CO', 'BED BUG CHEM' )
AND ( "Invoices"."TechID1" IN ( '298', '194', '330'  '391', '335')
    AND "Invoices"."TechID3" IN ( '298', '194', '330'  '391', '335')
    OR "Invoices"."TechID5" IN ( '298', '194', '330'  '391', '335')
)

让我们尝试不同的方式来安排数据,看看你得到的不同价值是什么:

此变体 - 您希望其中一个值同时位于TechID1和TechID3中(但由于它是一个列表,因此它们不必包含相同的值(TechID1 = 298和TechID3 = 194可以使用)除非TechID5包含值,否则您不关心TechID1或TechID3中的值(因此,如果TechID5 = 298,则TechID1等于299,TechID3等于301)

WHERE
-- Brian is 298, Cindy is 194, Jeremiah is 330, Monty is 391, and Tom is 335.
-- Technician AND Sales Rep
"Invoices"."ServiceCode" IN ( 'BED BUG CHEM CO', 'BED BUG CHEM' )
AND ( "Invoices"."TechID1" IN ( '298', '194', '330'  '391', '335')
    AND "Invoices"."TechID3" IN ( '298', '194', '330'  '391', '335'))
    OR "Invoices"."TechID5" IN ( '298', '194', '330'  '391', '335')
)

在这个变体中,您关心的是这些技术ID是否属于三个领域中的任何一个

    WHERE
    -- Brian is 298, Cindy is 194, Jeremiah is 330, Monty is 391, and Tom is 335.
    -- Technician AND Sales Rep
    "Invoices"."ServiceCode" IN ( 'BED BUG CHEM CO', 'BED BUG CHEM' )
AND ( "Invoices"."TechID1" IN ( '298', '194', '330'  '391', '335')
    OR "Invoices"."TechID3" IN ( '298', '194', '330'  '391', '335')
    OR "Invoices"."TechID5" IN ( '298', '194', '330'  '391', '335')
)

在此变体中,TechID1必须包含其中一个值,其中一个值可以是TechID3或TechID5

    WHERE
    -- Brian is 298, Cindy is 194, Jeremiah is 330, Monty is 391, and Tom is 335.
    -- Technician AND Sales Rep
    "Invoices"."ServiceCode" IN ( 'BED BUG CHEM CO', 'BED BUG CHEM' )
AND ( "Invoices"."TechID1" IN ( '298', '194', '330'  '391', '335')
    AND ("Invoices"."TechID3" IN ( '298', '194', '330'  '391', '335')
    OR "Invoices"."TechID5" IN ( '298', '194', '330'  '391', '335'))
)

在不了解您的业务规则的情况下,我们无法说明哪种变体是正确的。所有都在使用SQL代码。

在您想要混合AND和OR的任何时候使用括号是一个关键的做法,即使操作顺序会给出正确答案,因为在您需要修改查询的六个月内,您不知道是否这是不正确的,或者是否有意。每次使用()时,意图总是清晰的。