SSRS以逗号分隔的列表作为参数值

时间:2017-03-09 22:59:03

标签: reporting-services

我在SSRS上有一份报告。我的参数允许多个值。我的查询在WHERE语句中有:

WHERE AllDiag IN (@Diag)

我的用户应该可以输入类似Z34.83,R30.0,0000的内容。

这些是3个不同的搜索代码,因此从技术上讲,它正在寻找:

WHERE AllDiag IN ('Z34.83','R30.0','0000')

我尝试了各种各样的事情,例如使用=join(Parameters!Diag.Value,"','")在查询属性中创建参数属性,甚至输入带引号的代码列表,但似乎没有任何东西可以让它工作。

我甚至尝试了一些拆分功能,看看它是否单独搜索每个,但我不确定我是否正确使用它,因为似乎可能有一些功能应该在之前运行。

我没有想法。非常感谢任何帮助!

4 个答案:

答案 0 :(得分:1)

我假设你的数据集使用了你所说的WHERE子句

WHERE AllDiag IN (@Diag)

我还假设您无法轻松生成可供选择的参数值列表。

因此,要创建一个允许用户手动输入值列表的参数,只需在@Diag参数上设置“允许多个值”即可。然后,用户只需键入每个值并在每个值之后按Enter键。 注意不需要逗号只需逐个输入就可以输入。

当SSRS看到使用IN子句将多值参数传递给SQL语句时,它会自动将其转换为动态SQL,包括添加逗号。如果使用SQL事件探查器跟踪报告,则可以看到生成的SQL。

答案 1 :(得分:1)

这里有很多答案并没有真正指向解决方案。

问题:@Parameter值以逗号分隔的NVARCHAR值传递到SQL,而不是数据值列表,您可以JOIN使用或使用WHERE子句。通过过程调用传递给SQL Server时,参数的数据类型也会丢失。

SQL Server 2016+中的解决方案是使用内置的“ split_string”函数,该函数从单个定界字段返回值列表。

DECLARE @Parameter nvarchar(max);
Select *
FROM [dbo].[MyTable] a
JOIN (Select [value] FROM string_split(@Parameter)) b
ON a.ID=b.Value

根据您希望SSRS传递的数据类型,可能需要CAST的值字段。例如,DATE值可能如下所示:

DECLARE @Parameter nvarchar(max);
Select *
FROM [dbo].[MyTable] a
JOIN (Select CAST([value] as DATE) as [value] FROM string_split(@Parameter)) b
ON a.SomeDateValue=b.Value

在Sql Server 2014或更低版本中,您可以使用自定义函数将定界列表分成表行。 MSDN和StackOverflow上存在许多示例,这是非常详细的博客post,详细介绍了许多方法的优缺点。

这两种方法都适用于命令文本和存储过程数据集。

答案 2 :(得分:0)

我想我会与你分享这一切,以防万一你可能遇到过问题(比如我做过),将网页中的单个参数中的多个值传递给SSRS报告。

注意:这与传递多个参数不同,每个参数都有自己的值到报表中。后来,网上有很多例子。

当你需要基本上在报告的SQL命令中输入报告的SQL命令的值列表时,这非常有用,这些命令要使用"特殊的"函数,以及您不知道值可能需要的次数,因为用户可以选择从一个值到' n'价值观(但我们会达到极限,我稍后会解释)。它对于从您的网站生成Excel逐行摘录也很有用 - 比如稍后对Pivot表处理或图表进行处理。

不幸的是,使用IN()本身会欺骗很多人,他们无法弄清楚为什么它不起作用。这是因为如果您在SSRS中定义报表以期望参数直接进入IN()函数,系统会将值作为参数放在函数中并尝试比较什么是必要的参数& #34;数据类型"使用列的数据类型,您将收到错误。

如果您的报告中包含与此类似的SQL ...

SELECT t.Col1, t.Col2, etc
  FROM myTable t
WHERE t.myColumn IN (@myListOfValues)

其中@myListOfValues类似于"' value1',' value2',' value3',..."它"可能"工作,但我发现从ASP.net传递这样一个字符串到SSRS不起作用,ASP.net方面的字符串处理存在技术问题,加上你的系统和浏览器的限制。

要解决可能的问题,请在SQL Server数据库中创建一个函数,以接收由逗号分隔的值字符串,并允许该函数将列表转换为表格。这样,表可以很容易地使用SQL链接,并作为一种"参数馈送器传递#34;进入报告的SQL或数据集。

所以不要喋喋不休地开始使用代码和示例:

首先,让我们创建一个特殊的实用程序函数,将一个值列表转换为一个表,并且通过这个函数可以在你的项目中使用的方式来做到这一点 - 将由某些东西分隔的字符串拆分成表中的其他任何内容。 / p>

使用正常的右键单击NEW function命令打开SQL Server并创建一个新函数。像这样......

CREATE FUNCTION [dbo].[fnMakeTableFromList](@List VARCHAR(MAX),@Delimiter VARCHAR(255))
RETURNS TABLE
AS
  RETURN (SELECT Item = CONVERT(VARCHAR, Item)
          FROM (SELECT Item = x.i.value('(./text())[1]', 'varchar(max)')   FROM (SELECT [XML] = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter,'</i><i>')+ '</i>').query('.')) AS a
          CROSS APPLY [XML].nodes('i') AS x(i)) AS y
  WHERE  Item IS NOT NULL);

注意:分隔符不必是单个字符!再次用于使用关键字等分隔

注意函数中的XML逻辑和转换?这是因为ASP.Net将把一些HTML直接传递给SQL Server,我们将使用它将我们需要的数据剥离到表中。

运行带有一些值的函数进行测试:

SELECT * FROM dbo.fnMakeTableFromList ('a,b,c,d', ',');

您应该看到返回了4行数据......

a

B'/ P>

C

d

这是表格中的结果。

现在在SQL Reporting Services报告中使用此功能: 以下是我的报告:

SELECT DISTINCT s.StudentID
FROM tblStudents s
LEFT OUTER JOIN dbo.fnMakeTableFromList(@StudentList,',') AS list ON list.Item = s.StudentID
WHERE (@StudentList IS NULL
    OR @StudentList='')
  AND (l.Item IS NULL
    OR l.Item = s.StudentID)

注意如果没有传递任何值,我的示例也会报告每个学生ID。因此,请报告在tblStudents中找到的每个学生,或者根据给出的学生ID列表报告这些,并用逗号分隔。当您在SSRS中直接运行它时,系统会要求您输入参数@StudentList。在那里键入你需要用逗号分隔的值,你应该只获得那些学生ID。如果没有,请确保报告有效并且独立于#34;首先在转到ASP方面之前。

一旦您感到满意,您的报告就可以运行,并且SQL Server中的功能正常工作,那么我们就可以编写ASP.net方面的代码:

在您的ASPX代码页面(C#)中,我们需要控制列表的内容以及如何将其传递给SSRS。因为我们正在处理LIST&lt;&gt;在这里,我只是要说明如何使用LIST&lt;&gt;模仿一个数组。如您所知,C#没有像VB一样的数组术语。

因此,在您的ASP.net页面中,将此代码粘贴到您的PageLoad事件中......

protected void Page_Load(object sender, EventArgs e)
{
    //get parameters from the URL list
    string strStudentList = Request.QueryString["StudentList"];
    //create a List of parameters and pass it over to the report
    List<ReportParameter> paramList = new List<ReportParameter>();
    paramList.Add(new ReportParameter("StudentList", strStudentList));
    //run the report
    ReportViewer1.ServerReport.SetParameters(paramList);
}

当然,这里的一些对象必须在ASPx页面中定义。

例如,我使用母版页,正如您所看到的,我做了所有这些来创建一个邮件列表,用于在特殊粘性标签纸上打印。

<%@ Page Language="C#" MasterPageFile="~/rptsStudentAdministration/StudentAdminReports.master" AutoEventWireup="true" CodeFile="rptStudentLabels.aspx.cs" Inherits="rptsStudentAdministration_rptStudentLabels" Title="Student Mailing Labels" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <rsweb:reportviewer id="ReportViewer1" runat="server" font-names="Verdana" font-size="8pt"
        height="800px" processingmode="Remote" width="900px">
<ServerReport ReportServerUrl="<%$ AppSettings:ReportServerURL %>" ReportPath="/rptsStudentAdministration/rptStudentLabels"></ServerReport>
</rsweb:reportviewer>
</asp:Content>

确保您在.cs文件中也使用这些:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.Reporting.WebForms;

那就是人!

<强>结论:

如果您需要在SQL Server Reporting服务中生成一个报告,该报告依赖于用户选择none,一个或多个值来控制报告中的逻辑,那么可以考虑将它们作为单个参数传递并使用函数转将您的值放入表中以便于SQL管理。一旦SQL工作正常,您应该能够在设计模式下轻松生成报告并使用上面的ASPx逻辑,能够将逗号分隔的所有值传递到报表中。另一个好处是隐藏SSRS中的参数,这样用户就不必查看他们选择的值,并且您可以控制以编程方式生成的整个报表。

答案 3 :(得分:0)

我从Canadean_AS得到的答案是你应该设置一个多选参数。

但是,如果由于某种原因您难以接受单个逗号分隔的字符串到@Diag,您可以在查询中尝试以下内容:

WHERE CHARINDEX(','+ AllDiag +',',','+ @ Diag +',')&gt; 0

请注意,如果您的where子句使用此函数过滤大型数据集,则可能会遇到性能问题。

更有效的选择是将@Diag解析为自己的表,并将该表连接到FROM子句中的数据集。

相关问题