Sql server 从日期列表创建日期范围列表
我们目前存储的付款计划如下:Sql server 从日期列表创建日期范围列表,sql-server,Sql Server,我们目前存储的付款计划如下: 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 | D
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
但这是行不通的
我假设我需要添加一条记录,记录的起始日期为锚定成员
好的,它现在返回带有上面修改代码的数据
我现在的问题是,结果集不限于来自锚的AgreementID,我得到一个错误:
Msg 530,16级,状态1,第1行
声明终止了。在语句完成之前,已耗尽最大递归100
在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 |
|项目编号|到期日|日期从|日期到|应付金额|
----------------------------------------------------------------------------------------------------------------------------
|108 | 2013年2月1日00:00:00+0000 | 2013年1月14日00:00:00+0000 | 2013年2月25日00:00:00+0000 | 60|
|108 | 2013年2月26日00:00:00+0000 | 2013年2月26日00:00:00+0000 | 2013年2月28日00:00:00+0000 | 60|
|108 | 2013年3月1日00:00:00+0000 | 2013年3月1日00:00:00+0000 | 2013年3月14日00:00:00+0000 | 60|
|2013年3月15日08:00:00+0000 | 2013年3月15日00:00:00+0000 | 2013年3月25日00:00:00+0000 | 60|
您的错误是由于语句达到默认递归限制100而导致的。这可以通过使用更改。要使用未声明限制的提示,您的语句如下所示:
-- Statement that Executes CTE
SELECT AgreementID, DueDate, AmountDue
FROM CTE_Repayments
OPTION (MAXRECURSION 0)
警告:对递归使用无限制时要非常小心。此限制适用于短路无限递归循环。根据数据的外观,您的查询可能会很容易地螺旋输出并产生其他问题。我建议将
MAXRECURSION
增量增加到100以上,以找到合适的上限。在将此代码投入生产之前,一定要对此进行测试。如果没有以前的到期日期怎么办
?总是有一个日期列表。就像我说的,我们每次都会把StartDate作为第一个日期传入。有没有尝试过什么?在这个时间点上没有,这只是我开始写的一个新查询,我会生成一个带有行号的CTE,并使用上一行和下一行,使用DATEADD
填充到和从到,这段代码很好,谢谢,但在我的数据库上运行时,我无法得到相同的结果。也许他们还需要在窗口中进行分区:<代码>结束(按项目划分无订单依据…