Passing multiple values for a single parameter in Reporting Services
Asked Answered
G

21

72

I have several Multi-Select parameters in my report. I am trying to find a way to pass in multiple values for a single parameter in the web query string? If I pass in a single value, it works fine.

The report runs fine selecting multiple choices for a single param. My trouble lies in the web query string.

Gorga answered 4/2, 2009 at 16:24 Comment(1)
Also, Please refer: #33242506Lymphangial
T
104

Although John Sansom's solution works, there's another way to do this, without having to use a potentially inefficient scalar valued UDF. In the SSRS report, on the parameters tab of the query definition, set the parameter value to

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

In your query, you can then reference the value like so:

where yourColumn in (@<your param name>)
Tristis answered 6/2, 2009 at 8:42 Comment(12)
This was perfect. I'd like to add that if your having issues and this does not work for you, make sure that the parameters are in the correct order in the dataset in ssrs or it will not work when calling a wcf service.Pollen
UDF means User Defined Functions ?Lissie
@Adel - yes - UDF = User Defined FunctionTristis
I tried the same in SSRS 2005 with single parameter but it is not working. It is not showing any data. If I select only one value in report parameter then it is working but not for more than one value. Please find below for the details: @a = Join(Parameters!a.Value,",") Create PROCEDURE [dbo].[Test] @a Varchar(100) AS BEGIN select * from Test_Table where name in (@a) END -- Please help me.Cannoneer
@VenkateswarluAvula - you have a different problem; SQL Server does not support passing multiple values to an IN clause this way. There are literally hundreds of questions covering this topic - see stackoverflow.com/…Tristis
@Calvincalvina - I no longer have access to an SSRS 2005 environment to test this, but based on CodeGrue's answer to this thread, there may be problems using this solution with any int typeTristis
Would it make a difference that I am on SSRS 2010?Calvincalvina
I want to add that in SSRS 2008R2 there are no need to use JOIN. You can set parameter value just as Parameters!<your param name>.ValueOsteo
This approach won't work as expected. If you pass the parameter to the stored procedure where Customer is "Steve,Dave,Bill" then this won't match rows where Customer is "Steve" or "Dave" or "Bill". It will only match rows where the Customer is exactly "Steve,Dave,Bill".Gold
@EricNess - see my reply to VenkateswarluAvula above (Dec 19 '12)Tristis
After I posted this I realized that it would work for inline SQL, but not stored procedures. It was too late to edit my comment though...Gold
This won't work when you have an int as parameter. Instead there is an easier way by just passing the multi-value parameter as it is like this Select * from table where field IN (@MultivalueParameter)Recto
W
49

This is what I use when passing a multi-select param to another multi-select param.

=SPLIT(JOIN(Parameters!<your param name>.Value,","),",")
Wivestad answered 18/3, 2009 at 22:54 Comment(3)
This is the one I ended up having to use. Split by itself did not work, and Join alone only passed the first parameter in the multi select. +1 Thanks Minks!Rema
Too awesome!! ThanksManizales
If you by any chance have forgotten to set the parameter to "Allow multiple values", well set it :)Sharie
S
23

This is one of the poor supported features in SQL Reporting Services.

What you need to do is pass all of your selected items as a single string to your stored procedure. Each element within the string will be separated by a comma.

What I then do is split the string using a function that returns the provided string as a table. See below.

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

You can then reference the results in the where clause of your main query like so:

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

I hope this you find this solution to be of use. Please feel free to pose any questions you may have.

Cheers,John

Stryker answered 4/2, 2009 at 17:8 Comment(3)
Thanks. How about using nvarchar(max) to remove the length limitation?Tanto
How would "pass all of your selected items as a single string to your stored procedure" be done? Thank you for your helpAnthia
Worked like a charm! THANK YOU. Been searching for hours literally.Cacao
M
10

John Sansom and Ed Harper have great solutions. However, I was unable to get them to work when dealing with ID fields (i.e. Integers). I modified the split function below to CAST the values as integers so the table will join with primary key columns. I also commented the code and added a column for order, in case the delimited list order was significant.

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

Use this function as previously noted with:

WHERE id IN (SELECT Number FROM dbo.fn_SplitInt(@sParameterString,','))
Mas answered 26/3, 2010 at 13:0 Comment(0)
D
5

ORACLE:

The "IN" phrase (Ed's Solution) won't work against an Oracle connection (at least version 10). However, found this simple work-around which does. Using the dataset's parameter's tab turn the multi-value parameter into a CSV:

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

Then in your SQL statement's WHERE clause use the instring function to check for a match.

    INSTR(:name, TABLE.FILENAME) > 0
Derrik answered 2/11, 2009 at 22:21 Comment(2)
Nice. I'll give it a shot next time I'm doing maintenance on that report.Chandrachandragupta
Thanks Jeff. This issues seems to be still around in 11G as well.Later
S
4

I ran into a problem with the otherwise wonderful fn_MVParam. SSRS 2005 sent data with an apostrophe as 2 quotes.

I added one line to fix this.

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

My version of the fn also uses varchar instead of 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
Surge answered 19/4, 2011 at 19:8 Comment(0)
M
4

this worked for a distinct set of strings ( e.g. "START", "END", "ERROR", "SUCCESS" )

1)define a Report-Parameter ( e.g. @log_status ) and check "Allow multiple values"
enter image description here

2) define a dataset
3) open the dataset-properties window
3a) in the Query-Tab enter your query: e.g.

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

3b) in the Parameters-Tab enter your Parameter, e.g.
Parametername: @log_status ; Parametervalue: <<Expr>>
3c) for the Expr click on the "fx"-Button and enter:

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

enter image description here

finished! ( it's similar to Ed Harper's solution, but sorry to say this didn't work for me )

Mellman answered 24/5, 2018 at 19:54 Comment(0)
D
4

As of MSSQL 2016 - with compatibility level 130, you can utilize String_Split() to parse your joined parameter from SSRS. Say you wanted to populate a parameter from a query in SSRS and then pass that param to a stored proc or SSRS Shared Dataset:

  1. Add two datasets to your SSRS report, one that returns a list of values and labels to display in your parameter and one that has the actual data you're looking to filter. Each of these datasets can be a stored proc or shared dataset or embedded query.
  2. Create a parameter in SSRS that is NOT on the dataset you want to filter. Let's call it Customer
  3. Set Customer param to allow multiple values and set up Available Values tab with the dataset, labels, and values you want to display from the query.
  4. Right click the dataset you're looking to filter and add a parameter that IS defined in the stored procedure. Let's call it CustomerList.
  5. Click the expression button next to the value field for this parameter and do Join(Parameters!Customer.Value, ",")
  6. In your stored proc or shared dataset, utilize string_split to break the comma-delimited @CustomerList param into an array: Customer.CustID in (select value from string_split(@CustomerList, ',') where value = Customer.CustID)
Dahomey answered 23/4, 2019 at 14:48 Comment(0)
N
3

Modification of great John solution, solve:

  • "2 quotes" error
  • space after one of piece in parameter

    
    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
    
    
Nudd answered 3/2, 2012 at 12:53 Comment(0)
C
2

Just a comment - I ran into a world of hurt trying to get an IN clause to work in a connection to Oracle 10g. I don't think the rewritten query can be correctly passed to a 10g db. I had to drop the multi-value completely. The query would return data only when a single value (from the multi-value parameter selector) was chosen. I tried the MS and Oracle drivers with the same results. I'd love to hear if anyone has had success with this.

Chandrachandragupta answered 7/2, 2009 at 17:33 Comment(1)
I feel your pain. Spent much of the day fighting this myself before finally coming across an amazingingly simple solution. I've posted the answer here in case you're still interested.Derrik
C
2
  1. Create the dataset for the list in the report
  2. Right click the parameter and select available values
  3. Select newly created dataset as dataset
  4. Add the value passing to the stored procedure as value field
  5. Add the description of the parameter to label field (If the parameter is customerID then label could be CustomerName ex.)
  6. Finally, add following code to your stored procedure

declare @paramName AS NVARCHAR(500),

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

Conformist answered 27/6, 2013 at 13:58 Comment(0)
N
2

It would probably be easier to add the multi values to a table first and then you can join or whatever you'd like (even with wildcards) or save the data to another table for later use (or even add the values to another table).

Set the Parameter value via expression in the dataset:

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

The query itself:

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

INSERT INTO @Table EXEC sp_executeSQL @SearchValue 

Wildcard example:

SELECT * FROM YOUR_TABLE yt 

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

I'd love to figure out a way to do it without dynamic SQL but I don't think it'll work due to the way SSRS passes the parameters to the actual query. If someone knows better, please let me know.

Nuclei answered 5/8, 2016 at 18:42 Comment(0)
H
1

What you also can do is add this code in your stored procedure:

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

(Assuming @s is a multi-valued string (like "A,B,C"))

Hairstyle answered 13/12, 2010 at 15:12 Comment(0)
C
1

If you want to pass multiple values to RS via a query string all you need to do is repeat the report parameter for each value.

For example; I have a RS column called COLS and this column expects one or more values.

&rp:COLS=1&rp:COLS=1&rp:COLS=5 etc..
Charr answered 12/3, 2012 at 22:59 Comment(0)
M
1

I'm new to the site, and couldn't figure how to comment on a previous answer, which is what I feel this should be. I also couldn't up vote Jeff's post, which I believe gave me my answer. Anyways...

While I can see how some of the great posts, and subsequent tweaks, work, I only have read access to the database, so no UDF, SP or view-based solutions work for me. So Ed Harper's solution looked good, except for VenkateswarluAvula's comment that you can not pass a comma-separated string as a parameter into an WHERE IN clause and expect it to work as you need. But Jeff's solution to the ORACLE 10g fills that gap. I put those together with Russell Christopher's blog post at 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 and I have my solution:

Create your multi-select parameter MYPARAMETER using whatever source of available values (probably a dataset). In my case, the multi-select was from a bunch of TEXT entries, but I'm sure with some tweaking it would work with other types. If you want Select All to be the default position, set the same source as the default. This gives you your user interface, but the parameter created is not the parameter passed to my SQL.

Skipping ahead to the SQL, and Jeff's solution to the WHERE IN (@MYPARAMETER) problem, I have a problem all my own, in that 1 of the values ('Charge') appears in one of the other values ('Non Charge'), meaning the CHARINDEX might find a false-positive. I needed to search the parameter for the delimited value both before and after. This means I need to make sure the comma-separated list has a leading and trailling comma as well. And this is my SQL snippet:

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

The bit in the middle is to create another parameter (hidden in production, but not while developing) with:

  • A name of MYPARAMETER_LIST
  • A type of Text
  • A single available value of ="," + join(Parameters!MYPARAMETER.Value,",") + "," and a label that
    doesn't really matter (since it will not be displayed).
  • A default value exactly the same
  • Just to be sure, I set Always Refresh in both parameters' Advanced properties

It is this parameter which gets passed to SQL, which just happens to be a searchable string but which SQL handles like any piece of text.

I hope putting these fragments of answers together helps somebody find what they're looking for.

Macpherson answered 14/2, 2013 at 19:41 Comment(0)
F
1

In the past I have resorted to using stored procedures and a function to select multiple years in a SQL Server query for reporting services. Using the Join expression in the query parameter value as suggested by Ed Harper, still would not work with an SQL IN clause in the where statement. My resolution was to use the following in the where clause along with the parameter Join expression: and charindex (cast(Schl.Invt_Yr as char(4)) , @Invt_Yr) > 0

Fermin answered 20/3, 2013 at 19:25 Comment(0)
S
1

This is about using the join function to save a multi-value parameter and then restoring the exact same selections from the database later.

I just finished a report that had requirements that the parameters must be saved, and when the report is opened again (the report is passed an OrderID paramater), the values previously chosen by the user must be once again selected.

The report used a half of dozen parameters, each one had its own data set and resulting drop down list. The parameters were dependent upon the previous parameters to narrow the scope of the final selection, and when the report was "viewed" a stored procedure was called to populate.

The stored procedure received each of the parameters passed to it from the report. It checked a storage table in the database to see if any parameters were saved for that OrderID. If not, then it saved all the parameters. If so, it updated all of the parameters for that order (this is the case where the user changes their mind later).

When the report runs, there is a dataset dsParameters which is SQL text that goes out and selects the single row for that orderID if there is one. Each of the parameters in the report gets its default value from this dataset, and its selection list from a dataset dedicated to that parameter.

I ran into trouble with the multi-select parameter. I used a join(@Value,",") command in the main dataset parameter list, passing to the stored procedure a comma delimited string. But how to restore it? You can't feed the comma delimited string back to the default values box of the parameter.

I had to create another dataset to split the parameter, in a manner similar to what you are talking about. It looks like this:

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

Every time the form opens, this dataset checks the database for a saved string for this multi-valued parameter. If there is not one, it returns null. If there is on, it parses out the commas and creates a row for each of the values.

Then the default values box is set to this dataset, and fldDesc. It works! When I choose one or many, they save and replenish when the form is opened again.

I hope this helps. I searched for a while and did not find any mention of saving the join string in a database and then parsing it out in a dataset.

Sitdown answered 3/5, 2013 at 23:34 Comment(0)
C
1

This works great for me:

WHERE CHARINDEX(CONVERT(nvarchar, CustNum), @CustNum) > 0
Cence answered 29/5, 2014 at 15:28 Comment(1)
I have trouble piecing together how this answers the question. Can you elaborate a bit?Hanny
T
1

So multiply text values would end up in the query with single quotes around each I used =join(Parameters!Customer.Value,"','"). So after ".Value" that is comma, double-quote, single-quote, comma, single-quote, double-quote, close-bracket. simples :)

Telium answered 9/12, 2016 at 11:24 Comment(0)
T
1

The below solution worked for me.

  1. In the parameter tab of your dataset properties click on the expression icon (!http://chittagongit.com//images/fx-icon/fx-icon-16.jpg [fx symbol]) beside the parameter you need to allow comma delimited entry for.

  2. In the expression window that appears, use the Split function (Common Functions -> Text). Example shown below:

=Split(Parameters!ParameterName.Value,",")

Topography answered 12/6, 2018 at 0:13 Comment(0)
D
0

I needed solution for Oracle and I found this worked for me inside my query for my report for DB>=10g.

select * from where in ( select regexp_substr(,'[^,]+', 1, level) from dual connect by regexp_substr(, '[^,]+', 1, level) is not null );

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

Deltadeltaic answered 9/1, 2017 at 22:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.