SSRS报告多值报告过滤和分组

时间:2017-10-24 15:59:51

标签: sql-server reporting-services ssrs-2008-r2

让我们从基础开始。这是进入报告的数据的简化结构:

ID | Tags
1    |A| 
2    |A|B|
3    |B|
4    |A|C|D|
5    |B|D|
6    |D|A|C| --I added this row to show that tags could be in any order

我在报告中有一个参数,用户可以从列表中选择一个或多个标签(A,B,C,D)

以下是我希望在报告中看到的输出。它将被导出到Excel中,因此我将使用它来描述所需的输出。

示例报告输出:(标记参数选择:A和D)

工作表1 =显示所有记录=> [1,2,3,4,5,6]

工作表2 =显示与所有选定标签匹配的记录(必须包含A AND D的标记!)=> [4,6]

工作表3 =显示标记为A =>的记录[1,2,4,6]

工作表4 =显示标记为D =>的记录[4,5,6]

**注意:工作表3及以上将显示在单独的工作表中选择的每个标签,可能有1到N张。

目前在报告中我准备好了3张桌子:

表1:只显示完整的查询(简单易用!)并且有一个PageName ="所有记录"

表2:需要向下筛选完整查询以匹配上面的工作表2,并且将具有PageName ="过滤的记录" 这是问题#1!正在寻找关于过滤查询的想法!

表3:需要按标记对完整查询进行分组,但也只显示标记位于参数中所选标记列表中的组。 这是问题#2!不能从表2中获取过滤器然后分组,因为记录将丢失(例如标记D的数字5)

非常感谢任何和所有帮助!!

附加说明:

  • 可以更改标记分隔符(我选择|因为数据有逗号)
  • 无论分隔符如何,由于其他列中的聚合,标记只能返回一列(分隔列表)

1 个答案:

答案 0 :(得分:1)

这里有几个问题。我会先处理一个简单易用的问题。

我不确定我是否符合您的标准,因为我不理解你所说的一些内容,但无论如何,它可能会指向你正确的方向。

如果您还没有,请在数据库中创建拆分功能 如果你没有,你可以使用我多年前创建的那个。这不是完美的,但为我做的工作。

CREATE FUNCTION [fnSplit](@sText varchar(8000), @sDelim varchar(20) = ' ')
RETURNS @retArray TABLE (idx smallint Primary Key, value varchar(8000))
AS
BEGIN
DECLARE @idx smallint,
    @value varchar(8000),
    @bcontinue bit,
    @iStrike smallint,
    @iDelimlength tinyint
IF @sDelim = 'Space'
    BEGIN
    SET @sDelim = ' '
    END
SET @idx = 0
SET @sText = LTrim(RTrim(@sText))
SET @iDelimlength = DATALENGTH(@sDelim)
SET @bcontinue = 1
IF NOT ((@iDelimlength = 0) or (@sDelim = 'Empty'))
    BEGIN
    WHILE @bcontinue = 1
        BEGIN
--If you can find the delimiter in the text, retrieve the first element and
--insert it with its index into the return table.

        IF CHARINDEX(@sDelim, @sText)>0
            BEGIN
            SET @value = SUBSTRING(@sText,1, CHARINDEX(@sDelim,@sText)-1)
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END

--Trim the element and its delimiter from the front of the string.
            --Increment the index and loop.
SET @iStrike = DATALENGTH(@value) + @iDelimlength
            SET @idx = @idx + 1
            SET @sText = LTrim(Right(@sText,DATALENGTH(@sText) - @iStrike))

            END
        ELSE
            BEGIN
--If you can't find the delimiter in the text, @sText is the last value in
--@retArray.
 SET @value = @sText
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END
            --Exit the WHILE loop.
SET @bcontinue = 0
            END
        END
    END
ELSE
    BEGIN
    WHILE @bcontinue=1
        BEGIN
        --If the delimiter is an empty string, check for remaining text
        --instead of a delimiter. Insert the first character into the
        --retArray table. Trim the character from the front of the string.
--Increment the index and loop.
        IF DATALENGTH(@sText)>1
            BEGIN
            SET @value = SUBSTRING(@sText,1,1)
                BEGIN
                INSERT @retArray (idx, value)
                VALUES (@idx, @value)
                END
            SET @idx = @idx+1
            SET @sText = SUBSTRING(@sText,2,DATALENGTH(@sText)-1)

            END
        ELSE
            BEGIN
            --One character remains.
            --Insert the character, and exit the WHILE loop.
            INSERT @retArray (idx, value)
            VALUES (@idx, @sText)
            SET @bcontinue = 0  
            END
    END
END
RETURN
END

此函数只是将分隔的字符串拆分为表格中的组件。

然后我们可以使用CROSS APPLY为我们提供一个更易于使用的结果集。作为示例,我重新创建了您的示例数据,然后像这样使用CROSS APPLY ......

DECLARE @t table(ID int, Tags varchar(100))

INSERT INTO @t VALUES
(1,'|A|'),
(2,'|A|B|'),
(3,'|B|'),
(4,'|A|C|D|'),
(5,'|B|D|'),
(6,'|D|A|C|')

SELECT * FROM @t t
    CROSS APPLY fnSplit(Tags,'|') f
    WHERE f.Value != ''

这给了我们这个输出

ID  Tags    idx value
1   |A|     1   A
2   |A|B|   1   A
2   |A|B|   2   B
3   |B|     1   B
4   |A|C|D| 1   A
4   |A|C|D| 2   C
4   |A|C|D| 3   D
5   |B|D|   1   B
5   |B|D|   2   D
6   |D|A|C| 1   D
6   |D|A|C| 2   A
6   |D|A|C| 3   C

要获取所有记录

SELECT DISTINCT t.* FROM @t t
    CROSS APPLY fnSplit(Tags,'|') f
    WHERE f.Value != ''

要获取过滤后的记录,假设您有一个名为@pTags的参数,那么将数据集语句更改为

SELECT DISTINCT t.ID, f.Value FROM @t t
    CROSS APPLY fnSplit(Tags,'|') f
    WHERE f.Value != ''
    and f.Value IN (@pTags)

只要这是直接在您的数据集查询中并且参数是多值,那么这应该正确过滤,如果需要,使用DISTINCT。