By: Scott Murray | Updated: 2013-01-21 | Comments (45) | Related: > Reporting Services Development
Problem
After working with SQL Server Reporting Services ( SSRS ) for a time, eventually a report user will want to select more than one value for a parameter. How does SSRS handle multi-value parameters?
Solution
Allowing users to select multiple values from a parameter list is a great feature in SSRS; it allows report consumers more selection flexibility when running reports. However, how the parameters are passed to the dataset (or report object filters if used) varies depending on if the datasource is based on T-SQL embedded in a dataset within a report or if the data is passed via a stored procedure. Furthermore, once the report is run, a good practice is to display the selected parameter list somewhere within the report. The below instructions will convey the various techniques needed to utilize multi-value parameters. Finally, we will cover using a filter based multi-value parameters.
Embedded Parameters
Of the various options, passing multi value parameters to an embedded query is the less complex of the two methods. Utilizing this method, the report designer just needs to write a normal query, and utilize the "IN" key word in the criteria section of the query and then refer to the multi-value parameter using the @parameter name syntax within the parentheses portion of the IN statement. Using an AdventureWorks database and report example, the below code, inserted into a report dataset, notates the required syntax. This syntax should be somewhat standard to many of you who write T-SQL on a daily basis.
,DATEPART(Year, SOH.OrderDate) AS Year
,DATEPART(Month, SOH.OrderDate) AS MonthNumber
,DATENAME(Month, SOH.OrderDate) AS Month
,SUM(DET.LineTotal) AS Sales
FROM Sales.SalesPerson AS SP
INNER JOIN Sales.SalesOrderHeader AS SOH ON SP.BusinessEntityID = SOH.SalesPersonID
INNER JOIN Sales.SalesOrderDetail AS DET ON SOH.SalesOrderID = DET.SalesOrderID
INNER JOIN Sales.SalesTerritory AS ST ON SP.TerritoryID = ST.TerritoryID
INNER JOIN HumanResources.Employee AS E ON SOH.SalesPersonID = E.BusinessEntityID
INNER JOIN Person.Person AS P ON P.BusinessEntityID = SP.BusinessEntityID
WHERE (YEAR(SOH.OrderDate) IN (@ReportYear))
GROUP BY P.FirstName + ' ' + P.LastName
,SOH.SalesPersonID
,DATEPART(Year, SOH.OrderDate)
,DATEPART(Month, SOH.OrderDate)
,DATENAME(Month, SOH.OrderDate)
Next we will setup the parameter to accept multiple values. In the below example, a parameter called @ReportYear is already created, so right mouse clicking on the parameter (Report Year in the below example ) and selecting Parameter Properties will open the Report Parameter Properties window. Now check the Allow multiple values option. If you are setting up a new parameter, right mouse click on Parameters and then select New Parameter.
Subsequently, we will define the values to be used for our parameter list; this list will be the values presented to the report consumer. First, we define a dataset using the following simple query to generate a list of values for the ReportYear field.
Year(SOH.OrderDate) AS Year
FROM
Sales.SalesOrderHeader AS SOH
GROUP BY
Year(SOH.OrderDate)
ORDER BY SOH.Year
Finally, we set the dataset, Year_Lookup, to be used for the available values for the ReportYear parameter, and note below.
Now, the parameter is setup to accept multiple values. The setup required several steps including setting up our main report query to accept a parameter using the IN criteria, changing the allow multiple values option on the parameter properties, and last, generating a list of available values, in this example using another query. The end result is two fold. First, the report consumer now sees check boxes next to each parameter item which allows the user to select multiple values, as displayed below. Second, the report displays only the years selected.
Finally, the report data displays the years selected.
You may notice in the above figure that the title shows #Error after Sales Report for:.This field references the @ReportYear parameter; when this parameter was just a single value, it displayed correctly. However, now that the parameter is multiple values, SSRS is unable to display a value. Fortunately, the SSRS Join function can be used to display all the values selected and separate them with a fixed symbol. For this report we will break up the years with an &. The exact formula used is as follows:
The report with the JOIN function utilized is displayed below.
Multiple Value Parameters and Stored Procedure Based Datasets
Using stored procedures as the basis for SSRS datasets offers many advantages including potential reuse by other reports and potential performance advantages. However, multi-value parameters do not work well when getting passed to a stored procedure. Embedded SQL datasets noted above handle the parsing of the multiple values used in the IN criteria. To the contrary, when the multiple values are passed to a stored procedure, all the values are conveyed as one value.
The ReportYear parameter in our example report, for instance, would get passed as one value, "2006,2007,2008" which, of course would return no rows. Fortunately, we can use a string splitter function as part of our stored procedure to break up the years into multiple values. We will once again turn to using a Tally table by Jeff Moden; please see this article on using the Tally table to parse out the values, http://www.sqlservercentral.com/articles/Tally+Table/72993/.
I am not going to repeat Mr. Moden's code in the article, since it would be beneficial for you to understand what it can and cannot do. We will however use this function in dataset stored procedure which is noted below. Please make the following notes about the stored procedure. First we are passing in the concatenated multi-value parameter as a single entity and we use a varchar parameter (which must be large enough to accept the maximum length of all the parameters which might be selected). Next using the splitter function, the values are parsed out and placed into a temporary table, #YEAR_LIST. Last, the year criteria is moved from being part of the where clause to being part of the joins.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Scott Murray
-- Create date: 01/01/2013
-- Description: Sales by year query with parameter breakout
-- =============================================
ALTER PROCEDURE dbo.usp_Sales_by_Year
@ReportYear varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--Parse values into table which will be an inner join on main data query.
SELECT Item
INTO #YEAR_LIST
FROM
dbo.DelimitedSplit8K(@ReportYear,',')
--Main Dataset
SELECT P.FirstName + ' ' + P.LastName AS Employee
,DATEPART(Year, SOH.OrderDate) AS Year
,DATEPART(Month, SOH.OrderDate) AS MonthNumber
,DATENAME(Month, SOH.OrderDate) AS Month
,SUM(DET.LineTotal) AS Sales
FROM Sales.SalesPerson AS SP
INNER JOIN Sales.SalesOrderHeader AS SOH ON SP.BusinessEntityID = SOH.SalesPersonID
INNER JOIN Sales.SalesOrderDetail AS DET ON SOH.SalesOrderID = DET.SalesOrderID
INNER JOIN Sales.SalesTerritory AS ST ON SP.TerritoryID = ST.TerritoryID
INNER JOIN HumanResources.Employee AS E ON SOH.SalesPersonID = E.BusinessEntityID
INNER JOIN Person.Person AS P ON P.BusinessEntityID = SP.BusinessEntityID
INNER JOIN #YEAR_LIST AS YEARLIST ON YEAR(SOH.OrderDate) = YEARLIST.Item --Use join instead of where clause
--WHERE (YEAR(SOH.OrderDate) IN (@ReportYear))
GROUP BY P.FirstName + ' ' + P.LastName
,SOH.SalesPersonID
,DATEPART(Year, SOH.OrderDate)
,DATEPART(Month, SOH.OrderDate)
,DATENAME(Month, SOH.OrderDate)
END
GO
Certainly other methods exists to handle the parsing and include using the function in the where clause (I would avoid this method as I would not want to call this function for every row!). Alternatively, you could use a cross apply to match the years with the dataset. The final report utilizing the stored procedure methods is displayed subsequently.
Using Filters with Multiple Value Parameters
One last alternative involving the use of parameters pertains to dataset or object filters. Using filters at the object level, for example on a tablix, actually allows the same "larger" dataset to be used for multiple purposes while at the same time filtering the individual report parts based on a particular criteria. This setup can be advantageous in using a single dataset for all the report data; however, you also need to be careful about retrieving "very large" datasets while only using very small sets of the data. To setup a filter, first select the object in question, and then right mouse, click and select properties as illustrated below.
On the properties window, select the Filter window, and click add. Select the "field" or expression that is to be filtered, and then select the "In" Operator. Last, click on the fx expression builder button to the right of the value field to open the expression builder box.
As shown in the below illustration, within the filter expression box, click on Parameters under Category, and then double click on ReportYear Under years. What appears in the expression value box includes "(0)" at the end of name. This zero actually means retrieve the parameter in ordinal position 0 (ie the first parameter of the selected parameters). As you are probably realizing, that is not what we would like to filter on; we want to filter on all the parameter values selected. The trick to make the filter work, is as easy as removing the "(0)" from the expression.
Finally, the filter expression value actually should look as displayed below.
Now, the resulting report using a multiple value tablix filter is illustrated below.
Conclusion
Multiple value parameters are a wonderful tool within SSRS; their methods in practice, though, varies depending on their usage within embedded T-SQL, within stored procedures, or as part of an SSRS object filter. Embedded T-SQL is somewhat easier to use, however, the query can not be easily shared; to the contrary, using a stored procedure offers the ability to reuse a query (and other set based and logic structures), but you must parse parameter. Using a multiple value parameter with an object filter is also easy to implement as long as you know how to implement the parameter values in the filter. Last, it is often beneficial to display the parameters selected by the report consumer; the join function in SSRS allows you to display the parameter list easily in the report header or body.
Next Steps
- Single-Value and Multi-value Parameters (Report Builder and SSRS)-- http://msdn.microsoft.com/en-us/library/aa337292.aspx
- Creating Dynamic Report Filters in SQL Server Reporting Services SSRS -- http://www.mssqltips.com/sqlservertip/1897/creating-dynamic-report-filters-in-sql-server-reporting-services-ssrs/
- Hiding parameters and using default parameter values in SSRS reports -- http://www.mssqltips.com/sqlservertip/2202/hiding-parameters-and-using-default-parameter-values-in-ssrs-reports/
- Custom control and setup of SSRS report parameters from a web page -- http://www.mssqltips.com/sqlservertip/1751/custom-control-and-setup-of-ssrs-report-parameters-from-a-web-page/
- Check out this additional tip on multi-parameter SSRS reports
About the author
This author pledges the content of this article is based on professional experience and not AI generated.
View all my tips
Article Last Updated: 2013-01-21