简体   繁体   English

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

[英]SSRS report multivalue report filtering and grouping

Let's start with the basics. 让我们从基础开始。 Here's the simplified structure of the data coming into the report: 这是进入报表的数据的简化结构:

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

I have a parameter on the report where users can choose one or more tags from a list (A,B,C,D) 我在报表上有一个参数,用户可以从中选择一个或多个标签(A,B,C,D)

Here's the output I'd like to see on the report. 这是我想在报告中看到的输出。 It'll be exported into Excel so I'll be using that to describe the desired output. 它将被导出到Excel,因此我将使用它来描述所需的输出。

Sample report output: (Tag parameter selection: A and D) 样本报告输出:(标签参数选择:A和D)

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

Worksheet 2 = displays records that match all tags selected (must have tags for both A AND D!) => [4,6] 工作表2 =显示与所有选定标签匹配的记录(A D都必须有标签!)=> [4,6]

Worksheet 3 = displays records that have tag A => [1,2,4,6] 工作表3 =显示具有标签A => [1,2,4,6]的记录

Worksheet 4 = displays records that have tag D => [4,5,6] 工作表4 =显示具有标签D => [4,5,6]的记录

**Note: Worksheets 3 and up will show each of the tags selected in a separate worksheet, there could be 1 to N sheets. **注意:工作表3及更高版本将显示在单独的工作表中选择的每个标签,可能有1到N个工作表。

Currently in the report I have 3 tables ready to go: 目前,在报告中,我有3张表可供使用:

Table 1: Just displays the full query (nice and easy!) and has a PageName="All records" 表1:仅显示完整的查询(很简单!),并具有PageName =“ All records”

Table 2: Need to filter full query down to match Worksheet 2 above and will have a PageName="Filtered records" This is problem #1! 表2:需要过滤完整的查询以匹配上面的工作表2,并且将具有PageName =“ Filtered records” 这是问题1! Looking for ideas on a filter query! 寻找关于过滤查询的想法!

Table 3: Need to group the full query by Tag , but also only displays groups where the tag is in the list of tags selected in the parameter. 表3:需要按Tag对完整查询进行分组,但也仅显示该标签在参数中所选标签列表中的分组。 This is problem #2! 这是问题2! Can't just take the filter from Table 2 and then group because records would be missing (such as number 5 for tag D) 不能仅从表2中获取过滤器,然后进行分组,因为记录会丢失(例如标签D的数字5)

Any and all help would be greatly appreciated!! 任何和所有帮助将不胜感激!

Additional notes: 补充笔记:

  • Tag delimiter could be changed (I chose | because the data has commas) 可以更改标签定界符(我选择了|,因为数据有逗号)
  • Regardless of delimiter, tags can only come back in one column (delimited list) due to aggregation in other columns 无论定界符如何,由于其他列中的聚合,标记只能返回到一列(定界列表)中

There are several questions asked here. 这里有几个问题。 I'll deal with the one that will make you queries simple first. 我将处理使您首先简单查询的问题。

I'm not sure if I've met your criteria as I didn't understand some of what you said but anyway, it might point you in the right direction. 我不确定我是否满足您的条件,因为我不明白您所说的内容,但是无论如何,这可能会为您指明正确的方向。

Create a split function in your database if you don't already have one If you don't have one, you can use this one I created years ago. 如果您还没有一个拆分函数,请在数据库中创建一个拆分函数。如果没有,可以使用我几年前创建的拆分函数 It's not perfect but does the job for me. 这不是完美的,但可以为我完成工作。

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

This function just splits your delimited strings into it's components as a table. 此函数只是将您分隔的字符串拆分成表的组成部分。

We can then use CROSS APPLY to give us a result set that should be easier to work with. 然后,我们可以使用CROSS APPLY为我们提供一个更易于使用的结果集。 As an example I recreated your sample data then used CROSS APPLY like this... 例如,我重新创建了示例数据,然后像这样使用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 != ''

This gives us this output 这给了我们这个输出

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

To get all records just do 要获取所有记录,只需执行

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

To get the filtered records, assuming you have a parameter called @pTags then change the dataset statement to something like 要获取过滤的记录,假设您有一个名为@pTags的参数,然后将数据集语句更改为类似

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

As long as this is directly in your dataset query and the parameter is multi-value then this should filter correctly, use DISTINCT if required. 只要这直接在您的数据集查询中并且参数是多值,那么它就可以正确过滤,如果需要,请使用DISTINCT。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM