SQL项目月租租赁义务

时间:2014-07-22 16:09:00

标签: sql sql-server reporting-services

我有一份报告,该报告按年度按月分列退还的月租金。目前我们只用了六年,但希望报告计算到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    ...

1 个答案:

答案 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    ...