根据范围参数

时间:2015-10-29 13:40:27

标签: sql-server reporting-services

我有几年前写的SSRS报告。我把它像一颗定时炸弹一样建造起来。我以为它会在2022年停止工作,我当时希望它会成为别人的问题,但我认为它会比我预测的更早停止工作,可能是在2018年或2019年。所以我觉得有点不得不尽可能修复它。我可以很容易地修改我在其生命周期中添加5或10年的内容,但我想知道我是否可以这样做,以便报告中的年份列数量根据年份范围参数传递的年数而变化。

该报告按年度称为合同资金,旨在报告合同在合同期内每年获得的资金。为了解决这个问题,我计算了合同生效的月数。然后我计算每月燃烧率是什么(资金/月)。然后我计算每个特定年份每个合约活跃多少个月。最后,对于每个指定年份的每个月,我使用燃烧率乘以活跃月份来计算每份合约每年收到的每笔资金。容易,对吗? :)

运行报告时,连同一堆过滤参数,用户必须选择的主要参数是要检查的年限。可能的年份始于1982年(当我们开业时)并持续到2022年(40年)。这就是问题所在;在我创造40年范围的方式。

RDL由存储过程提供支持。 SP声明了40年变量,表示报告可以返回的总年数。这些变量中的每一个都填充SP中的唯一列。在RDL中,有40列对应于每个SP列。

他们说一张图片胜过千言万语。希望如此!

这是一个存储过程。您可以看到40年变量和40年列。 enter image description here

以下是SP的结果。每行有38年的列为空。 Stored Procedure Results

这是RDL。 40年中的每一年都由一列代表。它们可以隐藏,也可以根据visibility属性显示。 enter image description here

这是报告的结果。 enter image description here

所以,回顾一下,我的问题是我是否能够以不同的方式解决这个问题。业务需求是根据用户对年份日期范围的选择,生成可生成可变数量的年份输出列的报告。

先谢谢你的帮助!请询问是否需要澄清。

更新:这是我目前的代码:

declare @StartYear datetime  = '1/1/2009', @EndYear datetime = '12/31/2012'
Begin 
select 
cf.ContractFundingID, cf.StartDate, cf.EndDate
from ContractFunding cf 
where cf.StartDate <= @EndYear and cf.EndDate >= @StartYear
End
GO

我得到的结果如下:

ContractFundingID | StartDate | EndDate 
7363 | 2010-04-01 | 2011-02-28 
8767 | 2009-02-01 | 2011-12-31 
7466 | 2010-07-01 | 2011-06-30 
7503 | 2010-04-01 | 2011-03-31 

但我想要的是这样的:

ContractFundingID | StartDate | EndDate | Year 
7363 | 2010-04-01 | 2011-02-28 | 2009 
7363 | 2010-04-01 | 2011-02-28 | 2010 
7363 | 2010-04-01 | 2011-02-28 | 2011 
7363 | 2010-04-01 | 2011-02-28 | 2012 
8767 | 2009-02-01 | 2011-12-31 | 2009 
8767 | 2009-02-01 | 2011-12-31 | 2010 
8767 | 2009-02-01 | 2011-12-31 | 2011 
8767 | 2009-02-01 | 2011-12-31 | 2012 
7466 | 2010-07-01 | 2011-06-30 | 2009 
7466 | 2010-07-01 | 2011-06-30 | 2010 
7466 | 2010-07-01 | 2011-06-30 | 2011 
7466 | 2010-07-01 | 2011-06-30 | 2012 
7503 | 2010-04-01 | 2011-03-31 | 2009 
7503 | 2010-04-01 | 2011-03-31 | 2010 
7503 | 2010-04-01 | 2011-03-31 | 2011 
7503 | 2010-04-01 | 2011-03-31 | 2012 

我在SQL中想要的是每一行代表合同资金记录与我检查的日期范围的交集,这样我就可以为每个合同资金记录操纵每年的资金,可以跨越多年。

1 个答案:

答案 0 :(得分:2)

使用矩阵本来是一个更整洁的解决方案。这将允许您返回一个额外的字段来说明数据与哪一年相关,并自动创建所需的列数。如果任何年份没有数据,那么在基础查询中使用CROSS JOIN可能会填补空白。

在您尝试修补现有问题之前,我认为更多的研究可能对您有益

  • 查看矩阵

  • 的说明here 这里解释
  • CROSS JOIN

  • this是另一个关于如何使用CROSS JOINS填补空白的问题

我希望以上帮助。请询问您是否需要更多信息。

<强>更新

为了响应上述问题中的所需输出,下面是使用CROSS JOIN生成所需表格的示例。

首先,您需要在搜索日期之间的年份列表。使用常见的tbale表达式,您可以获得@Start@End日期之间的所有日期

DECLARE @Dates TABLE (YearNo INT)
;WITH n(n) AS
(
    SELECT YEAR(@Start)
    UNION ALL
    SELECT n+1 FROM n WHERE n < YEAR(@End)
)
INSERT INTO @Dates(YearNo)
SELECT n FROM n ORDER BY n

这将给出结果

YearNo
------
 1999
 2000
 (etc)

然后,您可以使用前面提到的交叉连接,如下所示

SELECT v.ContractFundingID v.StartDate, v.EndDate, d.YearNo
FROM  @VALUES v
CROSS JOIN @Dates d

给出结果

ContractFundingID | StartDate  | EndDate    | YearNo
------------------+------------+------------+--------
7363              | 2010-04-01 | 2011-02-28 | 1999
8767              | 2009-02-01 | 2011-12-31 | 1999
7466              | 2010-07-01 | 2011-06-30 | 1999
7503              | 2010-04-01 | 2011-03-31 | 1999
7363              | 2010-04-01 | 2011-02-28 | 2000
(etc)

我希望这会有所帮助。询问您是否需要进一步的帮助