表驱动的付款计划

时间:2013-06-08 11:54:53

标签: sql sql-server tsql

我的付款时间表根据“生效日期”为特定日期的付款时间表保留一行。

CREATE TABLE [dbo].[PaymentSchedule] (
    [PaymentScheduleId] INT  IDENTITY (1, 1) NOT NULL,
    [EffectiveDate]     DATE NOT NULL,
    [EffectiveDays]     INT  NOT NULL,
    CONSTRAINT [pk_PaymentSchedule] PRIMARY KEY CLUSTERED ([PaymentScheduleId] ASC)
);

因此,如果effectivedate是'01 -JAN-2013',而'EffectiveDays'是7,那么付款将在1月1日付款,之后每隔7天付款一次。因此,在1月8日,必须付款。在15日,必须付款等等。

如果effectivedate是'01 -JAN-2013',EffectiveDays是20,则第一笔付款是1月1日,下一个付款日是1月21日,接下来将是2013年2月9日等等。

我正在尝试做的是创建一个使用上表或者存储过程的函数,它返回“下一个付款日期”,并采用DATE类型。那么,根据传递的日期,下一个付款日期是什么?而且,“今天是付款日期”。

这可以有效地完成吗?例如,在7年时间内,我能判断一个日期是否是付款日吗?

3 个答案:

答案 0 :(得分:1)

您可以使用方法DATEDIFF(datepart,startdate,enddate)设置为datepart“dayofyear”,此方法的结果将为您提供两个日期之间的天数,并将此结果除以Modulo(%) EffectiveDays,如果结果为0则有付款日;如果没有,您将从最后一个付款日过去(如果您从有效日期提取它,您必须将休息日提交到下一个付款日)。

以下是DATEDIFF方法的一些文档: http://msdn.microsoft.com/en-us/library/ms189794.aspx

答案 1 :(得分:1)

您对问题的描述是错误的。如果第一笔付款是1月1日,则后续付款将在1月15日1月8日,依此类推。

关于当前日期的问题的答案是datediff()以及模数运算符。要查看今天是否为付款日期,请记下差异,看看它是否与您所看到的期间完全相同:

select getdate()
from PaymentSchedule ps
where datediff(day, ps.EffectiveDate, getdate()) % ps.EffectiveDays = 0;

%是模数运算符,它取两个值之间的余数。因此,3%2为1,10%5为0。

对于下一个日期,答案是类似的:

select dateadd(day,
               ps.EffectiveDays - datediff(day, ps.EffectiveDate, today) % ps.EffectiveDays,
               today) as NextDate
from PaymentSchedule ps cross join
     (select cast(getdate() as date) as today) const

我将此结构化为子查询,将当前日期定义为today。这样可以更容易地替换您可能想要的任何其他日期。

答案 2 :(得分:0)

我可能会回答错误的问题,但我认为以下代码会返回达到所选付款日期的付款时间表,如果这是您要查找的内容?

IF OBJECT_ID('tempdb..#PaymentSchedules') IS NOT NULL
    DROP TABLE #PaymentSchedules;

CREATE TABLE #PaymentSchedules
( PaymentScheduleID INT NOT NULL IDENTITY(1,1)
  CONSTRAINT PK_PaymentSchedules_PaymentScheduleID PRIMARY KEY
, EffectiveDate DATE NOT NULL
, EffectiveDays INT NOT NULL )
;

INSERT #PaymentSchedules (EffectiveDate, EffectiveDays)
VALUES
  ('20120401', 3)
, ('20120401', 2)
, ('20120401', 1)
, ('20120401', 7)
, ('20120401', 14)
;

DECLARE @PaymentDate DATE = '20140310';

WITH myCTE AS
(
  SELECT PaymentScheduleID, PaymentDate = EffectiveDate, EffectiveDays
  FROM #PaymentSchedules
  UNION ALL
  SELECT PaymentScheduleID, PaymentDate = DATEADD(DAY, EffectiveDays, PaymentDate), EffectiveDays
  FROM myCTE
  WHERE DATEADD(DAY, EffectiveDays, PaymentDate) <= @PaymentDate
)

SELECT * FROM myCTE
WHERE PaymentDate = @PaymentDate
OPTION (MAXRECURSION 10000)
;