在SQL中计算最接近的未来定期付款日期

时间:2009-07-09 21:16:32

标签: sql database sql-server-2005

我正在开发一个处理定期付款的应用程序 付款每两周进行一次,即

  • 付款1:2009-06-01
  • 付款2:2009-06-15
  • 付款3:2009-06-29

现在我需要一个SQL语句,可以计算WHERE子句中给定日期最近的下一个付款日期

即。 SELECT ... FROM ... WHERE someDate< [从给定日期计算下一个付款日期]

如果我在C#中这样做,我会去

static DateTime CalculateNextPayDateFrom(DateTime fromDate)
{
    var firstEverPayment = new DateTime(2009, 6, 1);
    var nextPayment = firstEverPayment;

    while (nextPayment < fromDate)
    {
        nextPayment += new TimeSpan(14, 0, 0, 0);
    }

    return nextPayment;
}

所以如果我这样做

Console.WriteLine(CalculateNextPayDateFrom(new DateTime(2009, 6, 12)).ToString());
Console.WriteLine(CalculateNextPayDateFrom(new DateTime(2009, 6, 20)).ToString());

输出

15/06/2009 12:00:00 a.m.
29/06/2009 12:00:00 a.m.

但是当我必须在SQL中执行此操作时,我完全陷入困境。

任何人都可以帮我解决这个问题吗?我正在使用SQL Server 2005

更新: 顺便说一句,我忘了提到数据库中没有最后的付款日期,必须在运行时计算。

4 个答案:

答案 0 :(得分:3)

要正确进行计算,您需要我所指的参考日期,例如:从您开始2周周期的日期。 (在您的代码中表示firstEverPayment声明)

鉴于您可以确定从现在到参考之间的天数,以获得天数。 除以14,但使用Floor向下舍入(例如计算出已经发生了多少2周的间隔) 添加1 - 向前移动两周的间隔。 (您可以使用天花板而不是地板跳过添加1) 乘以14 - 得到天数 使用添加日期添加那些日子。

这样的东西

select dateadd(dd,(Ceiling(datediff(dd,'1/1/09',getdate())/ 14)* 14),'1/1/09')

我使用1/1/09作为参考日期。

答案 1 :(得分:2)

这样的事情怎么样。抓住当年的当天,除以14得到余数,然后将差值从14添加到您的日期。您可能需要调整DaysOfYear以匹配您当年的第一笔付款......

declare @mydate datetime
set @mydate = '20090607'
select  DATEADD(dd, 14 - DATEPART(dayofyear, @mydate) % 14, @mydate)


set @mydate = '20090611'
select  DATEADD(dd, 14 - DATEPART(dayofyear, @mydate) % 14, @mydate)


set @mydate = '20090612'
select  DATEADD(dd, 14 - DATEPART(dayofyear, @mydate) % 14, @mydate)

set @mydate = '20090617'
select  DATEADD(dd, 14 - DATEPART(dayofyear, @mydate) % 14, @mydate)

答案 2 :(得分:0)

使用dateadd

create procedure GetNextDate
(
    @StartDate datetime,
    @FromDate datetime
) as
begin
    select 
        dateadd(day, 
            14*cast(datediff(day, @StartDate, @FromDate) / 14 + 1 as int), 
        @StartDate)
end

这会在@FromDate之后找到下一个付款日期,其开始日期为@StartDate

答案 3 :(得分:0)

我遇到了这个问题,试图解决一种方法,该方法可以根据不一定是过去的已知日期来计算“最近”支付期间的日期。

您的解决方案几乎让我到了那里,但这是在其他人正在寻找的情况下的完整解决方案:

(技巧是添加一个CASE / WHEN语句以检查refDate是否在testDate之前发生)

这可行:

DECLARE @refDate DATE = '3/6/18', @testDate DATE = '4/10/18'
SELECT DATEADD(DD,(CEILING(DATEDIFF(DD, @refDate, @testDate )/14)-CASE WHEN @refDate>@testDate THEN 1 ELSE 0 END)*14,@refDate)

Result:
Correctly returns "4/03/2018"

这有效:

DECLARE @refDate DATE = '3/6/18', @testDate DATE = '3/5/18'
SELECT DATEADD(DD,(CEILING(DATEDIFF(DD, @refDate, @testDate)/14)-CASE WHEN @refDate>@testDate THEN 1 ELSE 0 END)*14,@refDate)

Result:
Correctly returns "2/20/2018"