在Reporting Services中为单个参数传递多个值


67

我的报告中有几个“多项选择”参数。我正在尝试找到一种方法来为Web查询字符串中的单个参数传递多个值?如果我传递一个值,则效果很好。

该报告运行良好,可以为单个参数选择多个选项。我的麻烦在于网络查询字符串。


Answers:


100

尽管John Sansom的解决方案有效,但还有另一种方法可以执行此操作,而不必使用可能效率低下的标量值UDF。在SSRS报告中,在查询定义的“参数”选项卡上,将参数值设置为

=join(Parameters!<your param name>.Value,",")

在查询中,您可以像下面这样引用值:

where yourColumn in (@<your param name>)

1
@Adel-是-UDF =用户定义函数
Ed Harper

3
@VenkateswarluAvula-您遇到了其他问题;SQL Server不支持以IN这种方式将多个值传递给子句。有数以百计的问题涉及这一话题-见stackoverflow.com/...
埃德哈珀

1
@ tsqln00b -我不再有机会获得一个SSRS 2005年环境中测试这一点,但基于CodeGrue的回答这个线程,有可能使用任何这种解决问题的int类型
埃德哈珀

4
我想补充一点,在SSRS 2008R2中无需使用JOIN。您可以像设置参数值一样Parameters!<your param name>.Value
印度时间

3
这种方法无法按预期工作。如果将参数传递给Customer为“ Steve,Dave,Bill”的存储过程,则此行将不匹配Customer为“ Steve”,“ Dave”或“ Bill”的行。它只会匹配“客户”正好是“史蒂夫,戴夫,比尔”的行。
埃里克·尼斯

45

这是将多选参数传递给另一个多选参数时使用的。

=SPLIT(JOIN(Parameters!<your param name>.Value,","),",")

3
这是我最终不得不使用的。单独进行拆分不起作用,并且单独使用Join仅传递了多重选择中的第一个参数。+1感谢水貂!
Brett Salmiery

1
太棒了!! 谢谢
Tahari

如果您偶然忘记了将参数设置为“允许多个值”,请进行
适当

20

这是SQL Reporting Services中较差的支持功能之一。

您需要做的是将所有选定项作为单个字符串传递给存储过程。字符串中的每个元素都将用逗号分隔。

然后,我要做的是使用一个函数将字符串拆分,该函数将提供的字符串作为表返回。见下文。

ALTER FUNCTION [dbo].[fn_MVParam]
   (@RepParam nvarchar(4000), @Delim char(1)= ',')
RETURNS @Values TABLE (Param nvarchar(4000))AS
  BEGIN
  DECLARE @chrind INT
  DECLARE @Piece nvarchar(100)
  SELECT @chrind = 1 
  WHILE @chrind > 0
    BEGIN
      SELECT @chrind = CHARINDEX(@Delim,@RepParam)
      IF @chrind  > 0
        SELECT @Piece = LEFT(@RepParam,@chrind - 1)
      ELSE
        SELECT @Piece = @RepParam
      INSERT  @Values(Param) VALUES(CAST(@Piece AS VARCHAR))
      SELECT @RepParam = RIGHT(@RepParam,LEN(@RepParam) - @chrind)
      IF LEN(@RepParam) = 0 BREAK
    END
  RETURN
  END

然后,您可以像这样在主查询的where子句中引用结果:

where someColumn IN(SELECT Param FROM dbo.fn_MVParam(@sParameterString,','))

希望您能找到此解决方案。请随时提出任何问题。

干杯约翰


2
谢谢。如何使用nvarchar(max)删除长度限制?
Codeulike

如何完成“将所有选定项作为单个字符串传递给存储过程”?感谢您的帮助
LearnByReading 2015年

1
像魅力一样工作!谢谢。一直在寻找小时数。
Aimal Khan

9

John Sansom和Ed Harper有很好的解决方案。但是,当处理ID字段(即Integers)时,我无法使它们工作。我修改了下面的split函数,将值CAST转换为整数,以便表将与主键列结合在一起。我还注释了代码,并在顺序中添加了一列,以防分隔列表的顺序很重要。

CREATE FUNCTION [dbo].[fn_SplitInt]
(
    @List       nvarchar(4000),
    @Delimiter  char(1)= ','
)
RETURNS @Values TABLE
(
    Position int IDENTITY PRIMARY KEY,
    Number int
)

AS

  BEGIN

  -- set up working variables
  DECLARE @Index INT
  DECLARE @ItemValue nvarchar(100)
  SELECT @Index = 1 

  -- iterate until we have no more characters to work with
  WHILE @Index > 0

    BEGIN

      -- find first delimiter
      SELECT @Index = CHARINDEX(@Delimiter,@List)

      -- extract the item value
      IF @Index  > 0     -- if found, take the value left of the delimiter
        SELECT @ItemValue = LEFT(@List,@Index - 1)
      ELSE               -- if none, take the remainder as the last value
        SELECT @ItemValue = @List

      -- insert the value into our new table
      INSERT INTO @Values (Number) VALUES (CAST(@ItemValue AS int))

      -- remove the found item from the working list
      SELECT @List = RIGHT(@List,LEN(@List) - @Index)

      -- if list is empty, we are done
      IF LEN(@List) = 0 BREAK

    END

  RETURN

  END

如前所述使用此功能:

WHERE id IN (SELECT Number FROM dbo.fn_SplitInt(@sParameterString,','))

5

甲骨文:

“ IN”短语(“ ED解决方案”)不适用于Oracle连接(至少是10版)。但是,发现了这种简单的解决方法。使用数据集的参数选项卡,将多值参数转换为CSV:

    :name =join(Parameters!name.Value,",")

然后在您的SQL语句的WHERE子句中,使用instring函数检查匹配项。

    INSTR(:name, TABLE.FILENAME) > 0

2
真好 下次我对该报表进行维护时,我会试一试。
ScottLenart

2
谢谢杰夫。这个问题似乎在11G中也仍然存在。
BrandonG 2013年

2
谢谢您,度过了美好的一天!
拉尔夫177

4

我遇到了本来很棒的fn_MVParam的问题。SSRS 2005发送的数据中带有撇号的2个引号。

我添加了一行来解决此问题。

select @RepParam = replace(@RepParam,'''''','''')

我的fn版本也使用varchar而不是nvarchar。

CREATE FUNCTION [dbo].[fn_MVParam]
   (
    @RepParam varchar(MAX),
    @Delim char(1)= ','
   )
RETURNS @Values TABLE (Param varchar(MAX)) AS
/*
  Usage:  Use this in your report SP 
     where ID in (SELECT Param FROM fn_MVParam(@PlanIDList,','))
*/

BEGIN

   select @RepParam = replace(@RepParam,'''''','''')
   DECLARE @chrind INT
   DECLARE @Piece varchar(MAX)
   SELECT @chrind = 1
   WHILE @chrind > 0
      BEGIN
         SELECT @chrind = CHARINDEX(@Delim,@RepParam)
         IF @chrind > 0
            SELECT @Piece = LEFT(@RepParam,@chrind - 1)
         ELSE
            SELECT @Piece = @RepParam
         INSERT @VALUES(Param) VALUES(@Piece)
         SELECT @RepParam = RIGHT(@RepParam,DATALENGTH(@RepParam) - @chrind)
         IF DATALENGTH(@RepParam) = 0 BREAK
      END
   RETURN
END

3

修改约翰解决方案,解决:

  • “ 2个引号”错误
  • 参数之一后的空格

    
    ALTER FUNCTION [dbo].[fn_MVParam]
    (@RepParam nvarchar(4000), @Delim char(1)= ',')
    RETURNS @Values TABLE (Param nvarchar(4000))AS
    BEGIN
    //2 quotes error
    set @RepParam = replace(@RepParam,char(39)+char(39),CHAR(39))
    DECLARE @chrind INT
    DECLARE @Piece nvarchar(100)
    SELECT @chrind = 1 
    WHILE @chrind > 0
    BEGIN
      SELECT @chrind = CHARINDEX(@Delim,@RepParam)
      IF @chrind  > 0
        SELECT @Piece = LEFT(@RepParam,@chrind - 1)
      ELSE
        SELECT @Piece = @RepParam
      INSERT  @Values(Param) VALUES(CAST(@Piece AS VARCHAR(300)))
      //space after one of piece in parameter: LEN(@RepParam + '1')-1
      SELECT @RepParam = RIGHT(@RepParam,LEN(@RepParam + '1')-1 - @chrind)
      IF LEN(@RepParam) = 0 BREAK
    END
    RETURN
    END
    
    

2

只是一句话-试图让IN子句在与Oracle 10g的连接中工作时,我遇到了很多麻烦。我认为重写后的查询不能正确传递给10g db。我不得不完全放弃多值。选择一个值(从多值参数选择器)当查询将只返回数据。我尝试使用MS和Oracle驱动程序获得相同的结果。我很想听听是否有人成功做到了这一点。


1
我感到你很痛苦。花了整整一天的时间自己奋斗,最后才找到一个惊人的简单解决方案。如果您仍然有兴趣,我会在此处发布答案。
Jeff

2
  1. 为报告中的列表创建数据集
  2. 右键单击参数并选择可用值
  3. 选择新创建的数据集作为数据集
  4. 将传递给存储过程的值添加为值字段
  5. 将参数的描述添加到标签字段(如果参数为customerID,则标签可以为CustomerName ex。)
  6. 最后,将以下代码添加到您的存储过程中

声明@paramName AS NVARCHAR(500),

IF RIGHT(@paramName,1)=','BEGIN SET @paramName = LEFT(((@ paramName,LEN((@ paramName)-1)结束


2

首先将多个值添加到表中可能会更容易,然后您可以联接或随意添加(甚至使用通配符),也可以将数据保存到另一个表中以供以后使用(甚至将值添加到另一个表中) 。

通过数据集中的表达式设置参数值:

="SELECT DISTINCT * FROM (VALUES('" & JOIN(Parameters!SearchValue.Value, "'),('") & "')) 
AS tbl(Value)"

查询本身:

DECLARE @Table AS TABLE (Value nvarchar(max))

INSERT INTO @Table EXEC sp_executeSQL @SearchValue 

通配符示例:

SELECT * FROM YOUR_TABLE yt 

INNER JOIN @Table rt ON yt.[Join_Value] LIKE '%' + rt.[Value] + '%'

我很想找出一种无需动态SQL的方法,但由于SSRS将参数传递给实际查询的方式,我认为它不会起作用。如果有人知道更好,请告诉我。


2

这适用于一组不同的字符串(例如“ START”,“ END”,“ ERROR”,“ SUCCESS”)

1)定义一个Report-Parameter(例如@log_status)并选中“允许多个值”
在此处输入图片说明

2)定义数据集
3)打开数据集属性窗口
3a)在Query-Tab中输入您的查询:例如

select * from your_table where (CHARINDEX(your_column, @log_status,0) > 0)

3b)在参数标签中输入您的参数,例如
Parametername: @log_status ; Parametervalue: <<Expr>>
3c)对于Expr,单击“ fx”按钮并输入:

=join(Parameters!log_status.Value,",")

在此处输入图片说明

完蛋了!(这类似于Ed Harper的解决方案,但很遗憾地说这对我不起作用)


2

从MSSQL 2016开始-具有兼容级别130,您可以利用它String_Split()来从SSRS解析联接的参数。假设您想从SSRS中的查询中填充参数,然后将该参数传递给存储的proc或SSRS共享数据集:

  1. 将两个数据集添加到SSRS报告中,一个返回值和标签列表以显示在参数中,另一个包含要过滤的实际数据。这些数据集可以是存储的proc或共享的数据集或嵌入式查询。
  2. 在SSRS中创建一个不在要过滤的数据集上的参数。叫它吧Customer
  3. 设置Customer参数以允许多个值Available Values,并使用要从查询中显示的数据集,标签和值设置选项卡。
  4. 右键单击要过滤的数据集,然后添加一个在存储过程中定义的参数。叫它吧CustomerList
  5. 单击此参数的值字段旁边的表达式按钮,然后执行 Join(Parameters!Customer.Value, ",")
  6. 在存储的proc或共享数据集中,利用string_split将逗号分隔的@CustomerList参数拆分为一个数组: Customer.CustID in (select value from string_split(@CustomerList, ',') where value = Customer.CustID)

1

如果要通过查询字符串将多个值传递给RS,您需要做的就是为每个值重复报告参数。

例如; 我有一个称为COLS的RS列,该列需要一个或多个值。

&rp:COLS=1&rp:COLS=1&rp:COLS=5 etc..

1

您还可以做的是在存储过程中添加以下代码:

set @s = char(39) + replace(@s, ',', char(39) + ',' + char(39)) + char(39)

(假设@s是多值字符串(例如“ A,B,C”))


1

我是该网站的新手,无法确定如何对以前的答案发表评论,这就是我的感觉。我也无法投票给Jeff的职位,我相信这给了我答案。无论如何...

虽然我可以看到一些很棒的文章以及随后的调整是如何工作的,但我只能对数据库进行读取访问,因此没有UDF,SP或基于视图的解决方案对我有用。因此,Ed Harper的解决方案看起来不错,除了VenkateswarluAvula的注释,即您不能将逗号分隔的字符串作为参数传递到WHERE IN子句中,并期望它根据需要工作。但是Jeff针对ORACLE 10g的解决方案填补了这一空白。我将这些与拉塞尔·克里斯托弗(Russell Christopher)的博客文章放在一起,网址http://blogs.msdn.com/b/bimusings/archive/2007/05/07/how-do-you-set-select-all-as-the-default- for-multi-value-parameters-reporting-services.aspx,我有我的解决方案:

使用任何可用值源(可能是数据集)创建多选参数MYPARAMETER。就我而言,多选来自一堆TEXT条目,但是我敢肯定,通过一些调整,它可以与其他类型一起使用。如果要将“全选”作为默认位置,请设置与默认源相同的来源。这为您提供了用户界面,但是创建的参数不是传递给我的SQL的参数。

跳到SQL和Jeff对WHERE IN(@MYPARAMETER)问题的解决方案,我自己遇到了一个问题,因为其中一个值('Charge')出现在其他值之一('Non Charge' ),表示CHARINDEX可能会找到一个假阳性。我需要在参数之前和之后都在参数中搜索定界值。这意味着我需要确保以逗号分隔的列表也具有前导和尾随逗号。这是我的SQL代码段:

where ...
and CHARINDEX(',' + pitran.LINEPROPERTYID + ',', @MYPARAMETER_LIST) > 0

中间的一点是使用以下命令创建另一个参数(在生产环境中隐藏,但在开发过程中不隐藏):

  • MYPARAMETER_LIST的名称
  • 一种文字
  • 的单个可用值 ="," + join(Parameters!MYPARAMETER.Value,",") + ","和一个标签
    并不重要(因为它将不会显示)。
  • 默认值完全相同
  • 可以肯定的是,我在两个参数的Advanced属性中都设置了Always Refresh

正是这个参数传递给SQL,SQL恰好是一个可搜索的字符串,但是SQL像处理任何文本一样处理。

我希望将这些答案的片段放在一起可以帮助某人找到他们想要的东西。


1

过去,我曾使用存储过程和函数来选择SQL Server查询中的多年报表服务。按照Ed Harper的建议,在查询参数值中使用Join表达式,仍然不能与where语句中的SQL IN子句一起使用。我的解决方案是在where子句中使用以下参数以及参数Join expression:和charindex(cast(Schl.Invt_Yr as char(4)),@Invt_Yr)> 0


1

这是关于使用join函数保存多值参数,然后稍后从数据库中还原完全相同的选择。

我刚刚完成了一个报告,该报告要求必须保存参数,并且再次打开该报告(该报告已传递给OrderID参数)时,必须再次选择用户先前选择的值。

该报告使用了六个参数,每个参数都有自己的数据集和结果下拉列表。参数取决于先前的参数,以缩小最终选择的范围,并且在“查看”报告时,将调用存储过程来填充。

该存储过程从报告中接收传递给它的每个参数。它检查了数据库中的存储表,以查看是否为该OrderID保存了任何参数。如果不是,则保存所有参数。如果是这样,它将更新该订单的所有参数(用户稍后改变主意的情况)。

报表运行时,有一个数据集dsParameters,它是SQL文本,出了SQL文本,如果有则选择该orderID的单行。报表中的每个参数都从该数据集中获取其默认值,并从专用于该参数的数据集中获取其选择列表。

我在使用multi-select参数时遇到了麻烦。我在主数据集参数列表中使用了join(@Value,“,”)命令,将逗号分隔的字符串传递给存储过程。但是如何恢复呢?您不能将逗号分隔的字符串反馈回参数的默认值框。

我必须创建另一个数据集来拆分参数,方式与您所讨论的类似。看起来像这样:

IF OBJECT_ID('tempdb..#Parse','U') IS NOT NULL DROP TABLE #Parse

DECLARE @Start int, @End int, @Desc varchar(255)

SELECT @Desc = fldDesc FROM dbCustomData.dbo.tblDirectReferralFormParameters WHERE fldFrom = @From and fldOrderID = @OrderID

CREATE TABLE #Parse (fldDesc varchar(255))

SELECT @Start = 1, @End = 1

WHILE @End > 0
    BEGIN
        SET @End = CHARINDEX(',',@Desc,@Start)
        IF @End = 0 
            BEGIN
                INSERT #Parse SELECT REPLACE(SUBSTRING(@Desc,@Start,LEN(@Desc)),',','') AS fldDesc 
                BREAK
            END
        ELSE        
            BEGIN
                INSERT #Parse SELECT REPLACE(SUBSTRING(@Desc,@Start,@End-@Start),',','') AS fldDesc 
            END
        SET @Start = @End + 1
    END

SELECT * FROM #Parse

每次打开表单时,此数据集都会在数据库中检查此多值参数的保存字符串。如果没有,则返回null。如果存在,它将解析逗号并为每个值创建一行。

然后将默认值框设置为此数据集,并设置fldDesc。有用!当我选择一个或多个时,它们会在再次打开表单时保存并补充。

我希望这有帮助。我搜索了一会儿,却没有提到将连接字符串保存在数据库中然后在数据集中解析出来的内容。


1

这对我很有用:

WHERE CHARINDEX(CONVERT(nvarchar, CustNum), @CustNum) > 0

3
我很难拼凑出如何回答这个问题。你能详细说明一下吗?
马比

1

因此,乘以文本值最终会在查询中以单引号引起来,即我使用的每个引号都用= join(Parameters!Customer.Value,“','”)。因此,在“ .Value”之后是逗号,双引号,单引号,逗号,单引号,双引号,右括号。简单:)


1

以下解决方案为我工作。

  1. 在数据集属性的参数选项卡中,单击您需要允许逗号的参数旁边的表达式图标(!http://chittagongit.com//images/fx-icon/fx-icon-16.jpg [fx符号])分隔条目。

  2. 在出现的表达式窗口中,使用分割功能(通用功能->文本)。示例如下所示:

=拆分(Parameters!ParameterName.Value,“,”)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.