Замените IN на EXISTS или COUNT.Как это сделать.Чего здесь не хватает? - PullRequest
0 голосов
/ 24 июня 2010

Я использую ключевое слово IN в запросе в середине раздела. Поскольку я использую вложенный запрос и хочу заменить In на Exists из-за проблем с производительностью, которые, как мне сказали мои старшие, могут возникнуть.

Я пропустил какой-то столбец, что вы ищете в этом запросе. Этот запрос содержит несколько псевдонимов для удобства чтения.

Как мне это удалить.

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 

Какие новые проблемы могут возникнуть при замене IN на EXISTS или COUNT?

1 Ответ

4 голосов
/ 24 июня 2010

В принципе, как я понимаю ваш вопрос, вы спрашиваете, как я могу заменить это:

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 для внешних ключей? Я никогда не видел этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...