简化 SQL where exists in 子句
Simplify SQL where exists in clause
我想简化下面给定的过程,特别是我想删除大部分 where 子句过滤器,例如 IN 和 exists 子句。
为此,我使用了一个 CTE,还声明了一个临时 table 并用它来获取 select 查询,该查询自从它位于 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
感谢您的帮助。
你能不能试一试,如果这更快,并且仍然使用不同的过滤条件返回相同的值?
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;
我想简化下面给定的过程,特别是我想删除大部分 where 子句过滤器,例如 IN 和 exists 子句。
为此,我使用了一个 CTE,还声明了一个临时 table 并用它来获取 select 查询,该查询自从它位于 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
感谢您的帮助。
你能不能试一试,如果这更快,并且仍然使用不同的过滤条件返回相同的值?
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;