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

问题描述 投票:4回答:4

我正在处理一个处理定期付款的申请,每两周进行一次付款,即

  • 付款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

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

sql database sql-server-2005
4个回答
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作为参考日期。


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)

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


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"
© www.soinside.com 2019 - 2024. All rights reserved.