【问题标题】:Simplify SQL where exists in clause简化 SQL where exists in 子句
【发布时间】:2019-06-28 20:53:59
【问题描述】:

我想简化下面给出的过程,特别是我想删除大部分 where 子句过滤器,例如 IN 和 exists 子句。

为此,我使用了 CTE 并声明了一个临时表,并使用它来获取由于它位于 where in 子句中而长时间交谈的选择查询。如果您能向我展示一些技巧以简化此查询,我将不胜感激。

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

感谢您的所有帮助。

【问题讨论】:

    标签: sql-server tsql where exists


    【解决方案1】:

    如果这更快并且仍然返回具有不同过滤条件的相同值,您可以尝试吗?

    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;
    

    【讨论】:

    • 抱歉回复晚了。检索该值需要一秒钟。以前需要 9 秒。再次感谢您。
    猜你喜欢
    • 2013-04-17
    • 2019-05-18
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多