首页 > 解决方案 > 替换为空或存在内部查询逻辑以减少存储过程执行时间

问题描述

我的存储过程目前正在使用Is Null Or Exist与内部查询相结合的逻辑来过滤掉记录。存储过程是将多个逗号分隔的输入值转换为临时表(在生产场景中,输入记录数会高得多)。内部查询将这些临时表用于过滤条件。由于对查询执行时间的担忧,想用一个备用(如左连接)更改现有的内部查询。但需要保留相同的Is Null Or Exist逻辑。有什么建议么?

DECLARE @SelectedOfferes varchar(1000) = 'FLT10,SPL20'
DECLARE @SelectedBrandCode varchar(1000) = '208,406'
DECLARE @CategoryCode varchar(1000) = 'GMOVN2,CELSMR,LCDTV38IN'

CREATE TABLE #SelectedOfferes 
(
    DiscountCode VARCHAR(20)
)

CREATE TABLE #BrandCode
(
    BrandCode VARCHAR(20)
)

CREATE TABLE #CategoryCode
(
    CategoryCode VARCHAR(20)
)

IF @SelectedOfferes IS NOT NULL
BEGIN
    INSERT INTO #SelectedOfferes
        SELECT part 
        FROM dbo.[FormatTextByDelimiter] (@SelectedOfferes, ',')
END

IF @SelectedBrandCode IS NOT NULL
BEGIN
    INSERT INTO #BrandCode
        SELECT part 
        FROM dbo.[FormatTextByDelimiter] (@SelectedBrandCode, ',')
END

IF @CategoryCode IS NOT NULL
BEGIN
    INSERT INTO #CategoryCode
        SELECT part 
        FROM dbo.[FormatTextByDelimiter] (@CategoryCode, ',')
END

SELECT *    
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
WHERE (@SelectedOfferes IS NULL 
       OR (EXISTS (SELECT 1 FROM #SelectedOfferes OFR 
                   WHERE OFR.DiscountCode = P.DiscountCode)))
  AND (@SelectedBrandCode IS NULL 
       OR (EXISTS (SELECT 1 FROM #BrandCode BC 
                   WHERE BC.BrandCode = P.BrandCode)))
  AND (@CategoryCode IS NULL 
       OR (EXISTS (SELECT 1 FROM #CategoryCode CAT 
                   WHERE CAT.CategoryCode = P.CategoryCode)))

标签: sqlsql-servertsql

解决方案


此方法不能完全满足 OP 的要求,但在许多其他情况下有效

我对您的字符串拆分功能有一些疑问,它是基于集合还是循环查询?如果它不是基于集合的,那么您应该将其替换为 Jeff Moden 的 DelimitedSplit8K,可在http://www.sqlservercentral.com/articles/Tally+Table/72993/获得。

但无论哪种方式,以下对您最后一个查询的更改都应该有很大帮助。不需要 IS NULL 部分,因为它是 LEFT JOIN 并且如果构建它的变量为 NULL,则表将为空,因此您可以通过更少的引擎工作获得相同的结果。

SELECT *    
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
LEFT JOIN #SelectedOfferes OFR ON OFR.DiscountCode = P.DiscountCode
LEFT JOIN #BrandCode BC ON BC.BrandCode = P.BrandCode
LEFT JOIN #CategoryCode CAT ON CAT.CategoryCode = P.CategoryCode

推荐阅读