2016-12-22 71 views
0

我以前遇到過這個問題,從來沒有真正知道問題是什麼。我希望你大師之一那裏幫助解釋是什麼導致一個WHERE子句是ignored.The大畫面的問題是:什麼導致T-SQL中的WHERE子句被忽略?

當WHERE子句被忽略了,哪來開始尋找最好的地方?

什麼通常會導致此問題?

在這個特定的情況下,我試圖過濾掉某些服務代碼。我嘗試過使用NOT LIKE子句,或者只是使用IN()子句將我想要的服務代碼列入白名單,但聲明完全被忽略。每個服務代碼也與一個服務類相關聯,並且使用這些相同的運算符來過濾或白名單所需的服務類別什麼也不做。我試着將NOT LIKE和IN子句作爲我的WHERE下的第一個標準,如果它是一個操作順序問題,並且我已經在某處檢查了缺少的括號的三重檢查。所以,這個查詢返回的結果沒有任何錯誤消息,但它不會過濾掉不需要的行。

查詢的是一個爛攤子,因爲每一張發票有5個不同的領域,一個TechID可以在各場標誌着不同的東西,但這裏的查詢:

SELECT 
    (
     SELECT 
      "LocationCode" 
     FROM 
      "Locations" 
     WHERE 
      "Invoices"."LocationID" = "Locations"."LocationID" 
    ) AS "Location", 
    "Invoices"."OrderNum", 
    "Invoices"."ServiceCode", 
    "Invoices"."WorkDate", 
    "Invoices"."Total", 
-- "Classes"."Code" AS "ServiceClass", 
    (
     SELECT 
      "Employees"."Username" 
     FROM 
      "Employees" 
     WHERE 
      "Employees"."TechId" = "Invoices"."TechID1" 
    ) AS 'Tech', 
    (
     SELECT 
      "Employees"."Username" 
     FROM 
      "Employees" 
     WHERE 
      "Employees"."TechId" = "Invoices"."TechID2" 
    ) AS 'Helper', 
    (
     SELECT 
      "Employees"."Username" 
     FROM 
      "Employees" 
     WHERE 
      "Employees"."TechId" = "Invoices"."TechID3" 
    ) AS 'Sales Blue 1', 
    (
     SELECT 
      "Employees"."Username" 
     FROM 
      "Employees" 
     WHERE 
      "Employees"."TechId" = "Invoices"."TechID4" 
    ) AS 'Sales Blue 2', 
    (
     SELECT 
      "Employees"."Username" 
     FROM 
      "Employees" 
     WHERE 
      "Employees"."TechId" = "Invoices"."TechID5" 
    ) AS 'Term Self', 
    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 AS "Sales Rep", 
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 AS "Sale Status" 
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' 
    ) 
) 
OR -- Sales Blue 1, Sold but BSPC Lead 
"Invoices"."TechID3" IN (
    '298', 
    '194', 
    '330', 
    '391', 
    '335' 
) 
OR --Sales Blue 2 
"Invoices"."TechID4" IN (
    '298', 
    '194', 
    '330', 
    '391', 
    '335' 
) 
OR --Term Self (Gen) 
"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" 

任何意見或忠告,將不勝感激。謝謝!

+7

看起來像另一個人混合'OR'和'AND'的情況,而不是非常小心小括號。 –

+0

爲什麼你有雙引號內的所有字段和表? – FLICKER

+0

TechIDX字段是字符串還是數字?你將它們封裝在單引號中,表示它們是字符串。 –

回答

1

沒有任何情況會導致整個where子句被忽略。可能發生的情況是,where子句在OR的任一側都有表達式,並且如果一側評估爲真,那麼另一側無關緊要。當你合併大量的AND和OR時,你必須非常小心你的括號。

+0

有沒有什麼情況下where子句被忽略?我懷疑'WHERE MyColumn是NULL還是MyColumn不是NULL'不會被查詢優化器殺死。 – Sefe

+0

感謝您的支持。我會再次通過我的括號來查找錯誤。對於** Sefe **的觀點,我是SQL新手,對事物處理方式沒有太多瞭解。這就是激發這個問題的原因。 – Splattedone

+0

@Splattedone,按操作順序閱讀。 – HLGEM

1

這是對您的查詢進行重新格式化,我標記了我認爲您的or s出現故障的位置。

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 
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 ; 
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時使用括號是一種重要的做法,即使操作順序會給出正確的答案,因爲在六個月內當您需要修改查詢時,您將不知道這是是不正確的或者如果它是有意的。每次使用()時,意圖總是清晰的。