Упростите SQL там, где существует в предложении - PullRequest
0 голосов
/ 05 февраля 2019

Я хочу упростить приведенную ниже процедуру, особенно я хочу удалить большинство предложений where, таких как IN и существующие предложения.

Для этого я использовал CTE, а также объявил временную таблицу и использовал ее для получения запроса на выборку, который говорил долго, так как он был в предложении where.Буду признателен, если вы покажете мне некоторые хитрости, чтобы упростить этот запрос.

ALTER PROCEDURE dbo.GetMappingBranchScenarios 
    @Mapping INT
    @UserId INT= NULL
    @BranchId INT = NULL

SELECT 
    BS.BranchId,
    NULLIF( CC.Code, '' ) AS Code,
    BS.BranchName,
    BS.Active      
FROM
    Branch BS 
LEFT OUTER JOIN 
    Code CC ON CC.BranchId = BS.BranchId    
LEFT OUTER JOIN 
    BranchRule BRE ON BRE.MappingId = @Mapping
                   AND BRE.BranchId = BS.BranchId  
WHERE
    (BS.Active = 1 
        OR EXISTS (SELECT * FROM BranchRule BRE 
                   WHERE BRE.BranchId = BS.BranchId 
                     AND BRE.BranchId > 0 
                     AND BRE.MappingId = @MappingId))  
     AND (@UserId IS NULL     
             OR BS.BranchId IN (SELECT BranchId 
                                FROM branch2mapping.dbo.ListBranch(@UserId))
             OR EXISTS (SELECT 1 FROM dbo.SecondaryMapping 
                        WHERE Id = @UserId AND Admin = 1))
    AND BS.BranchId = (CASE WHEN BranchId is NULL THEN BS.BranchID ELSE @BranchId END)
    AND CC.Code =  (CASE WHEN @Code IS NULL THEN CC.Code ELSE @Code END)
ORDER BY
    CC.Code ASC

Что я сделал до сих пор:

IF OBJECT_ID('tempdb..#Temp', 'U') IS NOT NULL
    DROP TABLE #Temp

CREATE TABLE #Temp (BranchId INT) 

SELECT BranchId 
FROM branch2mapping.dbo.ListBranch(@UserId)

;WITH CTE AS 
(
    SELECT 
        BS.BranchId,
        NULLIF(CC.Code, '' ) AS Code,
        BS.BranchName, BS.Active      
    FROM
        Branch BS 
    LEFT OUTER JOIN 
        Code CC ON CC.BranchId = BS.BranchId    
    LEFT OUTER JOIN 
        BranchRule BRE ON BRE.MappingId = @Mapping
                       AND BRE.BranchId = BS.BranchId  
)
SELECT *  
FROM CTE
WHERE 
    (CTE.Active = 1     
     OR EXISTS (SELECT * FROM BranchRule BRE 
                WHERE BRE.BranchId = CTE.BranchId 
                  AND BRE.BranchId > 0 
                  AND BRE.MappingId = @MappingId))  
     AND (@UserId IS NULL     
             OR BS.BranchId IN (SELECT * FROM #Temp)
             OR EXISTS (SELECT 1 FROM dbo.SecondaryMapping 
                        WHERE Id = @UserId AND Admin = 1) 
         )
     AND BS.BranchId = (CASE WHEN BranchId is NULL THEN CTE.BranchID ELSE @BranchId END)
     AND CTE.Code = (CASE WHEN @Code IS NULL THEN CTE.Code ELSE @Code END)
 ORDER BY
     CTE.Code ASC

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 05 февраля 2019

Не могли бы вы попробовать, если это быстрее и все еще возвращает те же значения с разными критериями фильтрации?

ALTER PROCEDURE dbo.GetMappingBranchScenarios 
    @Mapping INT
    @UserId INT= NULL
    @BranchId INT = NULL


DECLARE @IsRuleExists BIT;
DECLARE @IsUrerADmin BIT;

IF EXISTS
(
    SELECT 1
    FROM Branch BS
    INNER JOIN BranchRule BRE 
        ON BRE.BranchId = BS.BranchId 
        AND BRE.BranchId > 0 
        AND BRE.MappingId = @MappingId
) 
BEGIN;
    SET @IsRuleExists = 1;
END;

IF EXISTS 
(
    SELECT 1 
    FROM dbo.SecondaryMapping 
    WHERE Id = @UserId AND Admin = 1
) OR @UserId IS NULL  
BEGIN;
    SET @IsUrerADmin = 1;
END;

CREATE TABLE #Branches
(
    [BranchId] INT
);

INSERT INTO #Branches ([BranchId])
SELECT BranchId 
FROM branch2mapping.dbo.ListBranch(@UserId);


SELECT 
    BS.BranchId,
    NULLIF( CC.Code, '' ) AS Code,
    BS.BranchName,
    BS.Active      
FROM Branch BS 
LEFT OUTER JOIN Code CC 
    ON CC.BranchId = BS.BranchId     
WHERE 
(
    BS.Active = 1 OR @IsRuleExists = 1
)  
AND 
(
    @IsUrerADmin = 1   
    OR 
    BS.BranchId IN (SELECT BranchId FROM #Branches)
)
AND BS.BranchId = (CASE WHEN BranchId is NULL THEN BS.BranchID ELSE @BranchId END)
AND CC.Code =  (CASE WHEN @Code IS NULL THEN CC.Code ELSE @Code END)
ORDER BY CC.Code ASC;
...