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

时间:2009-02-04 16:24:50

标签: sql reporting-services parameters query-string

我的报告中有多个Multi-Select参数。我试图找到一种方法来传递Web查询字符串中的单个参数的多个值?如果我传入一个值,它就可以正常工作。

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

21 个答案:

答案 0 :(得分:96)

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

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

在您的查询中,您可以像这样引用该值:

where yourColumn in (@<your param name>)

答案 1 :(得分:43)

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

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

答案 2 :(得分:21)

这是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,','))

我希望你能找到这个有用的解决方案。如果您有任何问题,请随时提出。

干杯,约翰

答案 3 :(得分:8)

John Sansom和Ed Harper有很好的解决方案。但是,在处理ID字段(即整数)时,我无法让它们工作。我修改了下面的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,','))

答案 4 :(得分:4)

ORACLE:

“IN”短语(Ed的解决方案)不适用于Oracle连接(至少版本10)。然而,发现这个简单的解决方法确实如此。使用数据集的参数选项卡将多值参数转换为CSV:

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

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

    INSTR(:name, TABLE.FILENAME) > 0

答案 5 :(得分: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

答案 6 :(得分:3)

修改伟大的John解决方案,解决:

  • “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
    
    

答案 7 :(得分:1)

我是网站的新手,无法想出如何评论之前的答案,这就是我认为应该如此。我也无法对杰夫的帖子投票,我认为这个帖子给了我答案。反正...

虽然我可以看到一些优秀的帖子和后续调整是如何工作的,但我只能读取数据库,因此没有UDF,SP或基于视图的解决方案适合我。所以Ed Harper的解决方案看起来不错,除了VenkateswarluAvula的评论,你不能将逗号分隔的字符串作为参数传递给WHERE IN子句并期望它能够按你的需要工作。但杰夫对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-in-reporting-services.aspx的博客文章放在一起,我有我的解决方案:

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

向前跳到SQL,以及Jeff对WHERE IN(@MYPARAMETER)问题的解决方案,我自己有一个问题,因为其中一个值('Charge')出现在其他一个值中('非充电'),意味着CHARINDEX可能会发现误报。我需要在参数之前和之后搜索分隔值。这意味着我需要确保以逗号分隔的列表也有一个前导和尾随逗号。这是我的SQL片段:

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

中间的位是创建另一个参数(隐藏在生产中,但不是在开发时):

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

这个参数传递给SQL,它恰好是一个可搜索的字符串,但SQL处理的任何一段文字都是如此。

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

答案 8 :(得分:1)

以下解决方案对我有用。

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

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

  3.   

    =分段(参数ParameterName.Value,&#34;!&#34)

答案 9 :(得分:1)

这适用于一组不同的字符串(例如&#34; START&#34;,&#34; END&#34;,&#34; ERROR&#34;,&#34; SUCCESS&#34;)<登记/>
1)定义报告参数(例如@log_status)并选中&#34;允许多个值&#34;
enter image description here

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点击&#34; fx&#34; -Button并输入:

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

enter image description here

完成! (它类似于Ed Harper的解决方案,但很遗憾地说这对我没用)

答案 10 :(得分:1)

因此,在我使用的每个= join(参数!Customer.Value,“','”)周围的单引号后,乘法文本值将最终出现在查询中。所以在“.Value”之后是逗号,双引号,单引号,逗号,单引号,双引号,闭括号。简单:)

答案 11 :(得分:1)

首先可以更容易地将多值添加到表中,然后您可以加入或者您喜欢的任何内容(即使使用通配符),也可以将数据保存到另一个表中供以后使用(或者甚至添加值到另一个表)。

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

="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将参数传递给实际查询的方式,我认为它不会起作用。如果有人知道的话,请告诉我。

答案 12 :(得分:1)

  1. 在报告中为列表创建数据集
  2. 右键单击参数并选择可用值
  3. 选择新创建的数据集作为数据集
  4. 将传递给存储过程的值添加为值字段
  5. 将参数说明添加到标签字段(如果参数为customerID,则label可以是客户名称ex。)
  6. 最后,将以下代码添加到存储过程
  7. 声明@paramName AS NVARCHAR(500),

    如果右(@ paramName,1)=',' 开始  SET @paramName = LEFT((@ paramName,LEN((@ paramName)-1) END

答案 13 :(得分:1)

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

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

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

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

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

我遇到了多选参数的问题。我在主数据集参数列表中使用了一个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。有用!当我选择一个或多个时,他们会在表格再次打开时保存并补充。

我希望这会有所帮助。我搜索了一段时间,没有发现任何提及在数据库中保存连接字符串然后在数据集中解析它。

答案 14 :(得分:1)

您还可以在存储过程中添加此代码:

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

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

答案 15 :(得分:1)

只是一个评论 - 我试图让一个IN子句与Oracle 10g的连接工作时遇到了一个伤害的世界。我不认为重写的查询可以正确传递给10g db。我不得不完全放弃多值。仅当选择单个值(来自多值参数选择器)时,查询才会返回数据。我尝试了MS和Oracle驱动程序,结果相同。我很想知道是否有人在这方面取得了成功。

答案 16 :(得分:0)

这对我很有用:

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

答案 17 :(得分:0)

过去,我已经使用存储过程和函数在SQL Server查询中选择多年来报告服务。使用Ed Harper建议的查询参数值中的Join表达式仍不适用于where语句中的SQL IN子句。我的解决方案是在where子句中使用以下参数以及参数Join expression:     和charindex(cast(Schl.Invt_Yr as char(4)),@ Invt_Yr)&gt; 0

答案 18 :(得分:0)

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

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

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

答案 19 :(得分:0)

我需要Oracle的解决方案,我发现这对我来说在我的查询中对我的DB&gt; = 10g。

从*中选择* 从dual中选择regexp_substr(,'[^,] +',1,level) connect by regexp_substr(,'[^,] +',1,level)不为null);

https://blogs.oracle.com/aramamoo/entry/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement

答案 20 :(得分:0)

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

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