2010-06-24 32 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