【问题标题】:Calculate Maturity date in SQL Server 2008在 SQL Server 2008 中计算到期日期
【发布时间】:2017-10-16 10:08:54
【问题描述】:

第一期的日期是加入日期。客户必须分期付款 10 次。每个月的每一期。因此,11 个月后,客户有资格以节省的金额购买产品。因此,到期日为加入日期后的 11 个月。 加入日期示例:2016 年 9 月 12 日 到期日:2017 年 7 月 12 日

如果客户在预定日期或当月到期日的任何一天付款,请不要延长到期日,否则到期日会延长。

Scenario 1: Pays on time
------------------------

Joining date: 12/Sep/2016
Expected output: 12/Jul/2017
加入日期 2016 年 9 月 12 日 Inst 没有付款日期 实际付款日期 考虑月份 1 2016 年 9 月 12 日 2016 年 9 月 12 日 2016 年 9 月 2 2016 年 10 月 5 日 2016 年 10 月 12 日 2016 年 10 月 3 2016 年 11 月 21 日 2016 年 11 月 12 日 2016 年 11 月 4 2016 年 12 月 12 日 2016 年 12 月 12 日 2016 年 12 月 5 2017 年 1 月 2 日 2017 年 1 月 12 日 2017 年 1 月 6 2017 年 2 月 2 日 2017 年 2 月 12 日 2017 年 2 月 7 2017 年 3 月 6 日 2017 年 3 月 12 日 2017 年 3 月 8 2017 年 4 月 6 日 2017 年 4 月 12 日 2017 年 4 月 9 2017 年 5 月 1 日 2017 年 5 月 12 日 2017 年 5 月 10 2017 年 6 月 7 日 2017 年 6 月 12 日 2017 年 6 月 到期日 2017 年 7 月 12 日

Scenario1

Scenario 2: when payments paid with delay
-----------------------------------------

Joining date: 12/Sep/2016
Expected output: 12/Sep/2017

Scenario2

 加入日期 12/Sep/2016

Inst 没有付款日期 实际日期 考虑付款月份
1 2016 年 9 月 12 日 2016 年 9 月 12 日 2016 年 9 月
2 2016 年 10 月 5 日 2016 年 10 月 12 日 2016 年 10 月
3 2016 年 11 月 21 日 2016 年 11 月 12 日 2016 年 11 月
4 2017 年 2 月 2 日 2016 年 12 月 12 日 2017 年 2 月
5 2017 年 2 月 2 日 2017 年 1 月 12 日 2017 年 3 月
6 2017 年 3 月 6 日 2017 年 2 月 12 日 2017 年 4 月
7 2017 年 3 月 6 日 2017 年 3 月 12 日 2017 年 5 月
8 2017 年 6 月 1 日 2017 年 4 月 12 日 2017 年 6 月
9 2017 年 6 月 1 日 2017 年 5 月 12 日 2017 年 7 月
10 2017 年 8 月 7 日 2017 年 6 月 12 日 2017 年 8 月

        到期日 2017 年 9 月 12 日

【问题讨论】:

  • 使用表结构和示例数据发布 SQL 将帮助我们获得解决方案,更详细的规则描述会有所帮助,据我所知,该规则似乎适用于每个月的错过付款延长一个月。

标签: sql sql-server-2008


【解决方案1】:

您的问题不清楚您要达到的目标。但是,我从你的两个例子中了解到,到期日应该与分期付款延迟一样多的月份。

甚至您的 Fiddler 场景也不清楚。有了这个小小的了解,我想出了下面的T-SQL来解决你的问题:

-- Schema generation
CREATE TABLE [dbo].[Payment](
    [InsNo] [int] PRIMARY KEY NOT NULL,
    [ReceiptDate] [datetime] NULL,
    [ScheduledDate] [datetime] NULL,
    [ConsideredMonth] DATETIME NULL,
) ON [PRIMARY]

GO

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(1, '2016-09-12 00:00:00', '2016-09-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(2, '2016-10-05 00:00:00', '2016-10-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(3, '2016-11-21 00:00:00', '2016-11-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(4, '2017-02-02 00:00:00', '2016-12-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(5, '2017-02-02 00:00:00', '2016-01-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(6, '2017-02-02 00:00:00', '2016-02-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(7, '2017-03-06 00:00:00', '2016-03-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(8, '2017-03-06 00:00:00', '2016-04-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(9, '2017-06-01 00:00:00', '2016-05-12 00:00:00');

INSERT INTO [Payment]([InsNo], [ReceiptDate], [ScheduledDate]) 
    VALUES(10, '2017-06-01 00:00:00', '2016-06-12 00:00:00');

GO

--   Solution using Cursor          
DECLARE @receiptDate DATETIME
        ,@lastInstForDate DATETIME
DECLARE @insNo INT

DECLARE _paymentsCursor CURSOR FAST_FORWARD
FOR
    SELECT p.InsNo
            ,p.ReceiptDate
    FROM   Payment p
    ORDER BY
            p.InsNo

OPEN _paymentsCursor

FETCH NEXT FROM _paymentsCursor INTO
    @insNo, @receiptDate
WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @lastInstForDate = p.ConsideredMonth
    FROM   Payment p
    WHERE  p.InsNo = @insNo - 1

    IF DATEADD(MONTH ,1 ,@lastInstForDate) > @receiptDate
        UPDATE Payment
        SET ConsideredMonth      = DATEADD(MONTH ,1 ,@lastInstForDate)
        WHERE InsNo = @insNo
    ELSE
        UPDATE Payment
        SET    ConsideredMonth = CAST(CAST(YEAR(ReceiptDate) AS VARCHAR(4)) + RIGHT('0' + CAST(MONTH(ReceiptDate) AS VARCHAR(2)) ,2) + '01' AS DATETIME)
        WHERE  InsNo = @insNo

    FETCH NEXT FROM _paymentsCursor INTO
        @insNo, @receiptDate
END

CLOSE _paymentsCursor
DEALLOCATE _paymentsCursor


DECLARE @lastPaymentDate DATETIME

DECLARE @maturityDate DATETIME
SELECT @maturityDate = DATEADD(month, 1, MAX(p.ConsideredMonth)), @lastPaymentDate = MAX(p.ReceiptDate) FROM dbo.Payment p
SET @maturityDate = CAST(CAST(YEAR(@maturityDate) AS VARCHAR(4)) + RIGHT('0' + CAST(MONTH(@maturityDate) AS VARCHAR(2)) ,2) + RIGHT('0' + CAST(DAY(@lastPaymentDate) AS VARCHAR(2)) ,2) AS DATETIME)
SET @maturityDate = DATEADD(DAY, 1, @maturityDate)

SELECT @maturityDate

【讨论】:

    【解决方案2】:

    试试这个 -

    SELECT MATURITY_DATE = CASE WHEN MAX([ReceiptDate]) <= DATEADD (MM , 9, '2016-09-12 00:00:00')
                           THEN DATEADD (MM , 10, '2016-09-12 00:00:00')
                           ELSE DATEADD (MM , 2, MAX([ReceiptDate])) END
    FROM [dbo].[Payment];
    

    【讨论】:

      【解决方案3】:

      你可以使用这个公式。

      select  DATEADD(DAY, 
                      DATEPART(DAY,(MIN([Actual Date]))) - DATEPART(DAY,(MAX([Payment Date]))),
                          DATEADD(MONTH, 
                              ( 11 - COUNT(*) )
                              , MAX([Payment Date])) )
      from @InstalmentTable
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多