我的任务是创建一份报告,根据单个续订日期和续订期限显示每个帐户包的续订日期。此报告应显示截至 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 |
+--------------+-----------------+
任何想法都会有很大的帮助。
最佳答案
您似乎需要一个数字表。一旦我们构建了它,剩下的只是一些 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;
关于sql - T-SQL 根据单个即将到来的日期和续订期限生成续订日期列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33711972/