使用CHARINDEX而不是IN子句来加速SSRS报告过滤器

时间:2015-07-30 23:15:53

标签: reporting-services

在某些情况下,我们在SSRS报告的过滤器中使用IN子句。通过在IN子句中使用数百个项目,其中许多都会导致性能问题。 如:

WHERE TableA.School IN (@School)

有时,多值参数处理起来非常棘手,您可能需要在RDL中执行= Join(Mypara.Value,“,”)并编写一个SQL函数将它们转换为一组SQL数据能够提供SQL SP。 (特别是一些旧版本的SSRS)。

FYI:用于将逗号分隔符字符串分解为记录集的函数:

CREATE function [dbo].[fnSpark_BreakUpList] (
    @List VARCHAR(MAX)
)
RETURNS @csvlist TABLE (Item VARCHAR(MAX))
AS
BEGIN
    DECLARE @Item VARCHAR(MAX)


    -- Loop through each item in the comma delimited list
    WHILE (LEN(@List) > 0)
    BEGIN
        IF CHARINDEX(',',@list) > 0
        BEGIN
            SET @Item = SUBSTRING(@List,1,(CHARINDEX(',', @List)-1))
            SET @List = SUBSTRING(@List,(CHARINDEX(',', @List) + DATALENGTH(',')),DATALENGTH(@List))
        END
        ELSE
        BEGIN
            SET @Item = @List
            SET @List = NULL
        END

        -- Insert each  item into the csvlist table
        INSERT into @csvlist (Item) VALUES (@Item)
    END
    RETURN
END
GO 

我将在短期内发布答案,以展示如何使用CHARINDEX提高性能。 (所以你不需要像上面那样......)

1 个答案:

答案 0 :(得分:0)

如果您实际上并不想从LONG分隔字符串中检索项目,而只想过滤它,那么CHARINDEX是一种更好的方法。

您可以使用:

,而不是使用IN Clause
WHERE CHARINDEX(','+TableA.School+',',','​+@School+',') > 0 

注意: 1.我在目标字符串的末尾添加一个额外的逗号' TableA.School'避免如果大字符串包含与过滤项目相同的子字符串的饱和度。 (例如我们有一所名为' AB'以及另一个' ABC'我们不希望在我们针对&#时选择' ABC' 39; AB' ....)

  1. 我在资源字符串的末尾添加了一个额外的逗号' @ School'确保单个项目/最后一个项目(它们将以逗号结尾)在我们定位时将被选中。

  2. 我在目标字符串的开头添加一个额外的逗号' TableA.School'避免如果大字符串包含与过滤项目相同的子字符串的饱和度。 (例如我们有一所名为' AB'以及另一个' CAB'我们不希望在我们针对&#时选择' CAB' 39; AB' ....)

  3. 示例:

    我正在使用:

    WHERE
    CHARINDEX(','+CAST(DENTIST4.wStudentYear AS VARCHAR(10))+',',','+@StudentYear+',') > 0 
    

    替换:

    WHERE
    DENTIST4.wStudentYear IN (@StudentYear) 
    

    对于我正在做的一个报告,这使得4000多页的渲染率从大约10分钟提高到大型数据库(11 G)的最小值。

    重要说明: 请确保传入数据集的过滤器报告参数使用JOIN子句。

    =Join(Parameters!MyParameter.Value,",")​
    

    希望这会有所帮助......

    重要提示:如果过滤器具有大量项目,则此方法仅提高性能,对于具有少量项目的任何过滤器,IN子句将执行更好的工作。