我们目前按以下方式存储付款时间表:
Item No | Due Date | Amount Due
108 | 2013-02-01 | 60.00
108 | 2013-02-26 | 60.00
108 | 2013-03-01 | 60.00
108 | 2013-03-15 | 60.00
注意:日期之间的差异是不一致的,即某些项目可能是几周,四周或几个月。
理想情况下,我需要解决的是如何将上表重新查询为以下格式:
Item No | Due Date | Date From | Date To | Amount Due
108 | 2013-02-01 | 2013-01-14 | 2013-02-25 | 60.00
108 | 2013-02-26 | 2013-02-26 | 2013-02-28 | 60.00
108 | 2013-03-01 | 2013-03-01 | 2013-03-14 | 60.00
108 | 2013-03-15 | 2013-03-15 | 2013-03-25 | 60.00
为了实现这一目标,额外的两个日期将是开始日期(2013-01-14)和今天的日期(2013-03-25)。
每个范围应从原始截止日期到下一个截止日期前一天。
任何建议都将不胜感激。
更新
这是我到目前为止所尝试的内容:
WITH
CTE_Repayments(AgreementID, DueDate, AmountDue)
AS
(
-- Anchor Member Definition
SELECT
AgreementID, StartDate, CONVERT(DECIMAL(9,2),0.00)
FROM
Loans AS L
WHERE
L.AgreementID = 111
UNION ALL
-- Recursive Member Definition
SELECT
RB.AgreementID, RB.DueDate, CONVERT(Decimal(9,2),RB.AmountDue)
FROM
(
SELECT *
FROM RepaymentBreakdown
WHERE AgreementID = 111
) AS RB
INNER JOIN
CTE_Repayments AS R
ON RB.AgreementID = R.AgreementID
)
-- Statement that Executes CTE
SELECT AgreementID, DueDate, AmountDue
FROM CTE_Repayments
但这不起作用。
我假设我需要添加一个以开始日期为锚点成员的记录。
好了,现在返回带有上述修改代码的数据。
我现在遇到的问题是结果集不限于来自Anchor的AgreementID,我收到错误:
Msg 530,Level 16,State 1,Line 1 声明终止。在语句完成之前,最大递归100已经用尽。
答案 0 :(得分:2)
您的错误是您的语句达到默认递归限制100的结果。可以使用MAXRECURSION
query hint更改此错误。要使用没有声明限制的提示,您的语句将如下所示:
-- Statement that Executes CTE
SELECT AgreementID, DueDate, AmountDue
FROM CTE_Repayments
OPTION (MAXRECURSION 0)
警告:非常小心,对递归没有限制。这个限制适用于短路无限递归循环。根据数据的外观,您的查询可能很容易转出并产生其他问题。我建议逐步将MAXRECURSION
增加到100以上,以找到合适的上限。在将此代码投入生产之前,一定要对此进行测试。
答案 1 :(得分:1)
在CTE中可能有一种更优雅的方式,但这是我的解决方案。
WITH cte (rowNo, itemNo, dueDate, amountDue) AS
(
SELECT ROW_NUMBER() OVER(ORDER BY [Due Date]) rowNo,
[Item No], [Due Date], [Amount Due]
FROM loans
)
SELECT a.itemNo, a.dueDate,
CASE WHEN c.dueDate IS NULL THEN '2013-01-14'
ELSE a.dueDate END AS dateFrom,
CASE WHEN b.dueDate IS NULL THEN '2013-03-25'
ELSE DATEADD(day, -1, b.dueDate) END AS dateTo,
a.amountDue
FROM cte AS a
LEFT JOIN cte AS b ON b.rowNo = a.rowNo + 1
LEFT JOIN cte AS c ON c.rowNo = a.rowNo - 1
<强>结果强>
| ITEMNO | DUEDATE | DATEFROM | DATETO | AMOUNTDUE | ---------------------------------------------------------------------------------------------------------------------------- | 108 | February, 01 2013 00:00:00+0000 | January, 14 2013 00:00:00+0000 | February, 25 2013 00:00:00+0000 | 60 | | 108 | February, 26 2013 00:00:00+0000 | February, 26 2013 00:00:00+0000 | February, 28 2013 00:00:00+0000 | 60 | | 108 | March, 01 2013 00:00:00+0000 | March, 01 2013 00:00:00+0000 | March, 14 2013 00:00:00+0000 | 60 | | 108 | March, 15 2013 00:00:00+0000 | March, 15 2013 00:00:00+0000 | March, 25 2013 00:00:00+0000 | 60 |