3

SSRS参数是一种痛苦。我希望能够通过允许用户访问许多不同的参数并使其成为可选项来重用报告以满足许多不同的需求。SSRS参数。允许“全部”或“空”

所以,如果我在开始时的代码,如:

Select * from mytable myt 
where myt.date between '1/1/2010' and '12/31/2010' 
and year(myt.date) = '2010' 
and myt.partnumber = 'XYZ-123' 

我想这些参数是可选的,所以我的第一次尝试是使参数默认为空,例如:

and (myt.partnumber = (@PartNumber) or (@PartNumber) is null) 

这有问题,因为如果有问题的数据库字段可以为空,那么您将删除记录,因为null不等于null。

然后我用如下代码:

DECLARE @BeginDate AS DATETIME 
DECLARE @EndDate AS DATETIME 
DECLARE @PartNumber AS VARCHAR(25) 
SET @Year = '..All' 
SET @BeginDate = '1/1/2005' 
SET @EndDate = '12/31/2010' 
SET @PartNumber = '..All' 
SET @Year = '..All' 

Select * from mytable myt 
where (myt.date between (@BeginDate) and (@EndDate)) 
and (year(myt.date) = (@Year) or (@Year) = '..All') 
and (myt.partnumber = (@PartNumber) or (@PartNumber) = '..All') 

这并不工作,因为年(myt.date)是一个整数,@Year不是。

所以,这是我的问题。

  1. 如何让我的日期可选?是简单地将它们默认为实际范围外的日期的最好方法,所以我返回所有值?
  2. 处理null或'..All'选项以使我的查询尽可能可读并允许我的用户拥有大多数数据类型的可选参数的最佳方法是什么?我宁愿不为

回答

1

我喜欢你的第三个代码块使用空。看起来好像你的WHERE子句可以被修正以使用非int值。该AND子句年线应该是这样的 - 不是我最好的T-SQL,但它应该让你在正确的方向:

and 1 = CASE @Year WHEN '..All' THEN 1 ELSE CASE WHEN year (myt.date) = CONVERT (int, @Year) THEN 1 ELSE 0 END END 

这将让你有”字符串值。 .All'或一个int值。要么会匹配正确。你可以用partnumber做同样的事情。

+0

我曾考虑过使用case语句,但问题是如果我有10个参数并且大多数是Case语句,SQL语句会变得非常冗长和混乱。 – DavidStein 2010-07-28 13:38:50

+1

你可以选择年份和partnumber(如-1)的幻数,然后你不需要投射或转换任何东西。这允许您使用第二个代码块。 – 2010-07-28 17:56:55

3

继续并允许空值,表示不应用过滤器。然后,您可以使用以下命令:

SELECT * 
FROM mytable myt 
WHERE COALESCE(myt.date, '1/1/1900') between COALESCE(@BeginDate, myt.date, '1/1/1900') and COALESCE(@EndDate, myt.date, '1/1/1900') 
    AND COALESCE(YEAR(myt.date), -1) = COALESCE(@Year, YEAR(myt.date), -1) 
    AND COALESCE(myt.partnumber, -1) = COALESCE(@PartNumber, myt.partnumber, -1) 

总之,如果任何变量值为NULL,然后比较列值本身,它有效地忽略了条件。更具体地说,当测试myt.date时,如果@BeginDate为NULL,则将较低范围值设置为等于myt.date值。使用@EndDate值进行相同的替换。即使如果@BeginDate@EndDate都为NULL,条件也是如此。

类似的方法也用于YEAR(myt.date)myt.partnumber。如果变量值为NULL,则将列值与自身进行比较,总是为true。

更新: 为每个COALESCE添加一个默认值来处理列值为NULL的情况。

+0

这不起作用,并且是我尝试的第一件事情(在问题中提到)。原因是,如果我的某个字段可以为空并且包含空值,那么记录不会被返回。 例如: AND myt.partnumber = COALESCE(@PartNumber,myt.partnumber) 如果myt.partnumber和@PartNumber都为null,则联接不会返回该记录。 – DavidStein 2010-07-28 13:40:58

+1

大卫 - 我错过了。但是,我还没有放弃......还没有。检查每个COALESCE中有附加值的更新。这对你有帮助吗? – bobs 2010-07-28 16:27:51

0

尝试这样,关键是要解决您的空参数值到代理空,也因为SQL服务器支持短路评价,把空检查一般应表现得更好。

Select * from mytable myt 
where (myt.date between (@BeginDate) and (@EndDate)) 
and (@Year IS NULL OR COALESCE(myt.date,'1900') = @Year) 
and (@PartNumber IS NULL OR ISNULL(myt.partnumber, '<NULL>') = (@PartNumber)