我有一份报告,该报告按年度按月分列退还的月租金。目前我们只用了六年,但希望报告计算到N
年。
这是我目前设置报告的方式
SELECT endDate
,term
,rentDue
,YEAR(endDate) AS yearLeaseEnds
,DATEDIFF(MONTH, @Date, endDate) AS totalMonthsRemaining --Count of months remaining in lease.
,(12 - MONTH(@Date)) AS monthRemainYear --number of months remaining this year.
,CASE
WHEN YEAR(@Date) = YEAR(endDate) THEN DATEDIFF(month, @Date, endDate) * rentDue --For leases ending the same year as the date selected
ELSE (12 - MONTH(@Date)) * rentDue --For leases that do not end the same year as the date selected.
END AS 'CurrentYear'
,CASE
WHEN YEAR(@Date) + 1 > YEAR(endDate) THEN 0 --exclude leases that ended prior year.
WHEN YEAR(@Date) + 1 = YEAR(endDate) THEN MONTH(endDate) * rentDue --When the end date is current year calculate the rent due for that year.
ELSE 12 * rentDue
END AS 'YearOne'
,CASE
WHEN YEAR(@Date) + 2 > YEAR(endDate) THEN 0 --exclude leases that ended prior year.
WHEN YEAR(@Date) + 2 = YEAR(endDate) THEN MONTH(endDate) * rentDue --When the end date is current year calculate the rent due for that year.
ELSE 12 * rentDue
END AS 'YearTwo'
... -- add CASE statements for each projected year
FROM leases
正如您所看到的,我必须为每年添加一份CASE声明,我想预计应付的租金。我尝试了一个WHILE循环,但我不熟悉SQL循环。
DECLARE @i AS INT; --loop counter
DECLARE @n AS INT; --years to project
DECLARE @Date DATE; --date to project rent obligations as of.
SET @Date = '2014-06-30'
SET @i = 0
SET @n = 5
WHILE @i <= @n
BEGIN
SELECT CASE
WHEN YEAR(@Date) + @i > YEAR(endDate) THEN 0 --exclude leases that ended prior year.
WHEN YEAR(@Date) + @i = YEAR(endDate) THEN MONTH(endDate) * monrent --When the end date is current year calculate the rent due for that year.
ELSE 12 * monrent --when the end date is in the future calculate the entire year's rent obligation.
END AS RentDue
FROM leases
SET @i = @i + 1
END;
有没有办法将循环的每个结果作为列返回?
也许做一个递归方法?但是我如何创建递归,因此它不是无限的。
修改:示例数据和预期结果。
样品
LeaseID | endDate | rentDue
--------+--------------+--------
1 | 2014-10-31 | 50
2 | 2015-03-31 | 25
3 | 2016-12-17 | 6000
4 | 2017-11-01 | 300
预期结果
LeaseID endDate rentDue ... CurrentYear YearOne YearTwo ... years to N
------------------------------------------------------------------------------------------------------------
1 2014-10-31 50 ... 200 0 0 ...
2 2015-03-31 25 ... 150 75 0 ...
3 2016-12-17 6000 ... 36000 72000 72000 ...
4 2017-11-01 300 ... 1800 3600 3600 ...
答案 0 :(得分:1)
一种解决方案是使用子查询返回您在租约之后的所有字段,并进行额外的年度计算,然后根据其他查询中的年数进行计算,并按最大年限过滤所有字段out参数。
DECLARE @YearsOut INT
DECLARE @Date DATETIME
SET @Date='01/01/2012'
SET @YearsOut=6
SELECT
CASE
WHEN YEAR(@Date) + YearsOut > YEAR(endDate) THEN 0 --exclude leases that ended prior year.
WHEN YEAR(@Date) + YearsOut = YEAR(endDate) THEN MONTH(endDate) * rentDue --When the end date is current year calculate the rent due for that year.
ELSE 12 * monrent --when the end date is in the future calculate the entire year's rent obligation.
END AS RentDue
,YearsOut
FROM
(
SELECT *
,YearsOut=DATEDIFF(YEAR,@Date,endDate)
FROM
leases
)AS X
WHERE
YearsOut BETWEEN 0 AND @YearsOut
使用以下查询可以完成同样的操作,但请注意,每次评估条件时,不会比较INT值YearsOut,而是运行DATEDIFF()函数。
DECLARE @YearsOut INT
DECLARE @Date DATETIME
SET @Date='01/01/2012'
SET @YearsOut=6
SELECT
CASE
WHEN YEAR(@Date) + DATEDIFF(YEAR,@Date,endDate) > YEAR(endDate) THEN 0 --exclude leases that ended prior year.
WHEN YEAR(@Date) + DATEDIFF(YEAR,@Date,endDate) = YEAR(endDate) THEN MONTH(endDate) * rentDue --When the end date is current year calculate the rent due for that year.
ELSE 12 * monrent --when the end date is in the future calculate the entire year's rent obligation.
END AS RentDue
FROM
leases
WHERE
DATEDIFF(YEAR,@Date,endDate) BETWEEN 0 AND @YearsOut
另一个小问题。对于任何重复使用函数的值,您可以通过在子查询中运行一次函数或在查询之前将值计算为常量参数来保存一些计算...
DECLARE @YearsOut INT
DECLARE @StartYear INT
DECLARE @Date DATETIME
DECLARE @EndYear DATETIME
SET @Date='01/01/2012'
SET @YearsOut=6
SET @StartYear=YEAR(@Date)
SET @EndYear=YEAR(@Date) + @YearsOut
SELECT
CASE
WHEN YearsOutCalc > endYear THEN 0 --exclude leases that ended prior year.
WHEN YearsOutCalc = endYear THEN endMonth * rentDue --When the end date is current year calculate the rent due for that year.
ELSE 12 * monrent --when the end date is in the future calculate the entire year's rent obligation.
END AS RentDue
FROM
(
SELECT *
,endYear=YEAR(endDate)
,endMonth=MONTH(endDate)
,YearsOutCalc=DATEDIFF(YEAR,@Date,endDate) + @StartYear
FROM
leases
)AS X
WHERE
YearsOutCalc BETWEEN @StartYear AND @EndYear
至于每年显示一年...您不需要在查询中返回这些列。而是使用列,按照您的leaseID分组的列组。这将推动您的数年前提到的最大年数。
RowGroupLeaseID Header----- |<--ColumnGroupYearsOut
LeaseID endDate rentDue | <Fields!YearsOutLabel.Value>
----------------------------------------------------------------------------------------
RowGroupLeaseID Detail----- |
<LeaseID> <ednDate> <rentDue> | <Fields!YearsOutValue.Value>
这会给你类似的东西:
LeaseID endDate rentDue ... CurrentYear YearOne YearTwo ... years to N
------------------------------------------------------------------------------------------------------------
1 2014-10-31 50 ... 200 0 0 ...
2 2015-03-31 25 ... 150 75 0 ...
3 2016-12-17 6000 ... 36000 72000 72000 ...
4 2017-11-01 300 ... 1800 3600 3600 ...