我正在处理一个处理定期付款的申请,每两周进行一次付款,即
现在我需要一个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
更新:顺便说一句,我忘了提到数据库中没有最后的付款日期,必须在运行时计算。
要正确地进行计算,您需要我将其称为参考日期,例如:从您开始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作为参考日期。
这样的事情怎么样?抓住当年的当天,除以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)
使用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
。
我在尝试解决一种基于已知日期(根据过去不一定)的“最近”支付期日期的方法时遇到了这个答案。
您的解决方案几乎让我在那里,但这是完整的解决方案,以防其他任何人正在寻找:
(诀窍是添加一个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"