在 SQL Server 2008 中计算到期日期
Posted
技术标签:
【中文标题】在 SQL Server 2008 中计算到期日期【英文标题】:Calculate Maturity date in 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 将帮助我们获得解决方案,更详细的规则描述会有所帮助,据我所知,该规则似乎适用于每个月的错过付款延长一个月。 【参考方案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
【讨论】:
以上是关于在 SQL Server 2008 中计算到期日期的主要内容,如果未能解决你的问题,请参考以下文章
需要在 SQL Server 2008 中查找两个日期之间的日期
在 SQL Server 2008 R2 和 SQL Server Compact 4 中存储日期/时间数据的最佳方式