2013-03-25 25 views
-1

我們目前存儲支付表的列表中創建日期範圍的名單如下:從日期

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)。

每個範圍應該從原始到期日到下一個到期日的前一天。

任何意見,將不勝感激。


UPDATE

這裏是我到目前爲止已經試過:

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, Level 16, State 1, Line 1 The statement terminated. The maximum recursion 100 has been exhausted before statement completion.

+0

如果沒有以前的「到期日期」,該怎麼辦? – Kermit 2013-03-25 14:16:53

+0

總是有一個日期列表。就像我說的那樣,我們將每次都傳入StartDate作爲第一個日期。 – 2013-03-25 14:17:46

+0

有沒有*已經嘗試過? – Kermit 2013-03-25 14:18:37

回答

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 |

See the demo

+0

嗨 這段代碼非常好,謝謝,但是我在運行數據庫時無法得到相同的結果。 – 2013-03-25 15:56:02

+0

也許他們還需要在窗口中進行分區:? 'OVER(按項目劃分否按順序...' – 2013-03-25 16:19:44

2

你的錯誤是你的發言擊中100這個默認的遞歸限制的結果可以通過使用MAXRECURSION query hint改變。爲了不宣佈限制使用提示,你的說法是這樣的:

-- Statement that Executes CTE 
SELECT AgreementID, DueDate, AmountDue 
FROM CTE_Repayments 
OPTION (MAXRECURSION 0) 

警告:使用你的遞歸沒有限制要非常小心。該限制適用於短路無限遞歸循環。根據數據的外觀,您的查詢可能會輕鬆轉換並創建其他問題。我會建議逐步增加你的MAXRECURSION高於100來找到合適的上限。在將此代碼投入生產之前,肯定會對此進行測試。