2010-06-24 34 views
0

我在查詢中使用了IN關鍵字。由於我使用嵌套查詢,並且想要替換InExists,這是由於我的老人告訴我可能會出現的性能問題。將IN替換爲EXISTS或COUNT。怎麼做。這裏缺少什麼?

我錯過了一些專欄,你在這個查詢中查找什麼。該查詢包含一些用於可讀性的別名。

我該如何刪除它。

SELECT TX.PK_MAP_ID AS MAP_ID 
     , MG.PK_GUEST_ID AS Guest_Id 
     , MG.FIRST_NAME 
     , H.PK_CATEGORY_ID AS Preference_Id 
     , H.DESCRIPTION AS Preference_Name 
     , H.FK_CATEGORY_ID AS Parent_Id 
     , H.IMMEDIATE_PARENT AS Parent_Name 
     , H.Department_ID 
     , H.Department_Name 
     , H.ID_PATH, H.DESC_PATH 
FROM   
    dbo.M_GUEST AS MG 
     LEFT OUTER JOIN 
    dbo.TX_MAP_GUEST_PREFERENCE AS TX 
      ON 
       (MG.PK_GUEST_ID = TX.FK_GUEST_ID) 
     LEFT OUTER JOIN 
    dbo.GetHierarchy_Table AS H 
      ON 
       (TX.FK_CATEGORY_ID = H.PK_CATEGORY_ID) 
WHERE  
    (MG.IS_ACTIVE = 1) 
     AND 
    (TX.IS_ACTIVE = 1) 
     AND 
    (H.Department_ID IN -----How to remove this IN operator with EXISTS or Count() 
       ( 
       SELECT C.PK_CATEGORY_ID AS DepartmentId 
       FROM 
        dbo.TX_MAP_DEPARTMENT_OPERATOR AS D 
         INNER JOIN 
        dbo.M_OPERATOR AS M 
          ON 
           (D.FK_OPERATOR_ID = M.PK_OPERATOR_ID) 
            AND 
           (D.IS_ACTIVE = M.IS_ACTIVE) 
         INNER JOIN 
        dbo.L_USER_ROLE AS R 
          ON 
           (M.FK_ROLE_ID = R.PK_ROLE_ID) 
            AND 
           (M.IS_ACTIVE = R.IS_ACTIVE) 
         INNER JOIN 
        dbo.L_CATEGORY_TYPE AS C 
          ON 
           (D.FK_DEPARTMENT_ID = C.PK_CATEGORY_ID) 
            AND 
           (D.IS_ACTIVE = C.IS_ACTIVE) 
       WHERE  
        (D.IS_ACTIVE = 1) 
         AND 
        (M.IS_ACTIVE = 1) 
         AND 
        (R.IS_ACTIVE = 1) 
         AND 
        (C.IS_ACTIVE = 1) 
      )--END INNER QUERY 
    )--END Condition 

如果我用EXISTS或COUNT取代IN,可能會出現什麼新問題?

回答

4

基本上,我明白你的問題,你問我怎麼能代替這個:

where H.department_id in (select departmentid from...) 

與此:

where exists (select...) 

或本:

where (select count(*) from ...) > 1 

這是非常坦率的。一種方法可能是這樣的:

WHERE... 
    AND EXISTS (select c.pk_category_id 
       from tx_map_department_operator d 
       inner join m_operator as m 
        on d.fk_operator_id = m.pk_operator_id 
       inner join l_user_role l 
        on m.fk_role_id = r.pk_role_id 
       inner join l_category_type c 
        on d.fk_department_id = c.pk_category_id 
       where h.department_id = c.pk_category_id 
       and d.is_active = 1 
       and m.is_active = 1 
       and r.is_active = 1 
       and c.is_active = 1 
      ) 

我刪除了is_active上的額外連接,因爲它們是多餘的。您應該測試它如何與索引一起運行,因爲這可能會更快。但我對此表示懷疑。但它是值得的比較無論是更快地添加加盟條款(join on ... and x.is_active=y.is_active),或在where子句(x.is_active=1 and y.is_active=1 and z.is_active=1...

在檢查和我建議你只是用exists,而不是count(*),因爲我知道,存在應該在找到1行後停止,而計數可能會繼續執行直到完成,然後與您的參考值(count> 1)進行比較。

另外,這是一個奇怪的列命名標準,你有。你真的有主鍵的PK前綴和外鍵的FK前綴嗎?我從來沒有見過。

+0

是的,我認爲命名標準也很煩人。他們肯定會使查詢不易讀。 – SiN 2010-06-24 12:29:03

+0

SIN:我同意命名約定有點荒謬,但我不是PM也不是TL,只是一個SE所以不能改變它,並且必須遵循已經告訴我們的東西,因爲它不能幫助我自己。這裏我的問題是去除H.Department的影響。正如我在這裏所想的那樣,它將如何獲得相同的結果。 – 2010-06-24 12:44:55

+0

我認爲它應該加入H表。上面所做的更改。但是現在我不確定我是否理解這個意圖。在內部查詢中使用H表可能會顯着減慢它的速度。 – MJB 2010-06-24 12:58:21