我的任务是创建一个报告,根据单个续订日期和续订条款显示每个帐户包的续订日期。该报告应显示截至2018年12月底的所有续约日期。
所有帐户包都有一个月(1到12)的期限和当前的续订日期(下一个即将到来)(AccountPackage表)。
+--------------+---------------+--------------+
| AccountPkgID | PkgTermMonths | RenewalDate |
+--------------+---------------+--------------+
| 1 | 1 | 12/1/2015 |
| 2 | 3 | 12/1/2015 |
| 3 | 6 | 12/1/2015 |
| 4 | 12 | 12/1/2015 |
+--------------+---------------+--------------+
我能够通过使用包表的笛卡尔积与所有月份的表(Report_MonthlyDates表)来处理所有月度包。
+----------------+
| dtfirstofmonth |
+----------------+
| 12/1/2015 |
| 1/1/2016 |
| 2/1/2016 |
| 3/1/2016 |
| . each month . |
| 12/1/2018 |
+----------------+
以下是我在下面提出的SQL,它仅用了1个月的包裹... 3个月或更长时间没有用。
SELECT AllPkgs.AccountPkgID, AllPkgs.PkgTermMonths, MonthlyPkgs.dtfirstofmonth
from
(SELECT AccountPkgID, PkgTermMonths, RenewalDate
FROM Accountpackage
WHERE RenewalDate >= '12/1/2015'
AND RenewalDate < '1/1/2019') AllPkgs
INNER JOIN
(SELECT dtfirstofmonth
FROM [Report_MonthlyDates]
WHERE dtfirstofmonth >= '12/1/2015'
AND dtfirstofmonth < '1/1/2019') MonthlyPkgs ON (AllPkgs.months = 1)
我提出的唯一另一个想法是光标,但它会有糟糕的表现。我希望能够用桌面功能或其他东西来做。
我想得到的输出:
+--------------+-----------------+
| AccountPkgID | RenewalDate |
+--------------+-----------------+
| 1 | 12/1/2015 |
| 1 | 1/1/2016 |
| 1 | … every month … |
| 1 | 12/1/2018 |
| 2 | 12/1/2015 |
| 2 | 3/1/2016 |
| 2 | 6/1/2016 |
| 2 | 9/1/2016 |
| 2 | 12/1/2016 |
| 2 | 3/1/2017 |
| 2 | 6/1/2017 |
| 2 | 9/1/2017 |
| 2 | 12/1/2017 |
| 2 | 3/1/2018 |
| 2 | 6/1/2018 |
| 2 | 9/1/2018 |
| 2 | 12/1/2018 |
| 3 | 12/1/2015 |
| 3 | 6/1/2016 |
| 3 | 12/1/2016 |
| 3 | 6/1/2017 |
| 3 | 12/1/2017 |
| 3 | 6/1/2018 |
| 3 | 12/1/2018 |
| 4 | 12/1/2015 |
| 4 | 12/1/2016 |
| 4 | 12/1/2017 |
| 4 | 12/1/2018 |
+--------------+-----------------+
任何想法都会有很大的帮助。
答案 0 :(得分:2)
您似乎需要一个数字表。一旦我们构造了它,剩下的只是一些SQL:
with numbers as (
select n.*
from (select row_number() over (order by (select null)) - 1 as n -- starts at 0
from master..spt_values
) n
where n < 100 -- 100 values should be quite sufficient for the end of 2018
)
select ap.AccountPkgID,
dateadd(month, n.n * ap.PkgTermMonths, ap.renewaldate) as renewaldate
from AccountPackage ap join
numbers n
on dateadd(month, n.n * ap.PkgTermMonths, ap.renewaldate) <= '2018-12-31'
order by AccountPkgID, n.n;