如何基于其他2个属性计算日期列?

时间:2019-02-11 10:52:08

标签: sql sql-server datetime sql-server-2012 sql-date-functions

我必须基于其他2个字段在运行时计算日期字段。

----------------------------------------------------------
Run Date   ||     Schedule       ||  Next Bill run date
-----------------------------[enter image description here][1]-----------------------------
----------------------------------------------------------
11/29/2018 ||     1st        ||  12/01/2018
----------------------------------------------------------
11/29/2018  ||     15th      ||   12/15/2018
----------------------------------------------------------
12/02/2018 ||   1st    ||   12/01/2019
----------------------------------------------------------
12/02/2018  ||  15th     ||      12/15/2018
----------------------------------------------------------
12/16/2018 ||   15th     ||     01/15/2019
----------------------------------------------------------

在上述情况下,应根据前2列填充下一个帐单运行日期。 共有4个条件,

  1. 如果同一月2日至15日与计划值之间的日期(运行日期)为“ 15”,则“下一次帐单运行”将为同一月的15日。

  2. 如果第16个(同一月)至1月(下一个月)与计划值之间的日期(运行日期)为“ 15”,则“下一个帐单运行”将是下个月的15号。

  3. 如果同一月2日至15日之间的日(运行日期)与计划的值是“ 1st”,则“下一次帐单运行”将是下个月的1号。

  4. 如果第16个(同一月)至1月(下个月)与计划值之间的日期(运行日期)为“ 1st”,则“下一个帐单运行”将为下个月的1号。

请参阅上表以获得更好的理解。请帮助我找出实施“下一个条例草案”的逻辑。感谢您的帮助。

我正在考虑使用'case'函数获取运行日期的datepart()。但是仍然与实现混淆

3 个答案:

答案 0 :(得分:1)

希望以下查询对您有所帮助。

set @lastDate := (SELECT LAST_DAY(now()) AS first_day);
set @firstDate := (SELECT DATE_ADD(DATE_ADD(LAST_DAY(now()),INTERVAL 1 DAY),INTERVAL - 1 MONTH) AS first_day);
select run_date,schedule,
case
when run_date between @firstDate and DATE_ADD(@firstDate, INTERVAL 14 DAY) and schedule ='15th' then DATE_ADD(@firstDate, INTERVAL 14 DAY)
when run_date between DATE_ADD(@firstDate, INTERVAL 15 DAY) and DATE_ADD(@firstDate, INTERVAL 1 MONTH) and schedule ='15th' then date_add(DATE_ADD(@firstDate, INTERVAL 14 DAY), INTERVAL 1 MONTH)
when run_date between @firstDate and DATE_ADD(@firstDate, INTERVAL 14 DAY) and schedule ='1st' then DATE_ADD(@firstDate, INTERVAL 1 MONTH)
when run_date between DATE_ADD(@firstDate, INTERVAL 15 DAY) and DATE_ADD(@firstDate, INTERVAL 1 MONTH) and schedule ='1st' then DATE_ADD(@firstDate, INTERVAL 1 MONTH)
end
as next_bill_run_date 
from your_table

在SQL Server中

declare @firstDate as date = '01-'+month(getdate())+'-'+year(getdate());
select run_date,schedule,
case
when run_date between @firstDate and DATEADD(DAY,14,@firstDate) and schedule ='15th' then DATEADD(DAY,14,@firstDate)
when run_date between DATEADD(DAY,15,@firstDate) and DATEADD(MONTH, 1, @firstDate) and schedule ='15th' then DATEADD(MONTH, 1, DATEADD(DAY,14,@firstDate))
when run_date between DATEADD(DAY,14,@firstDate) and schedule ='1st' then DATEADD(MONTH, 1, @firstDate)
when run_date between DATEADD(DAY,15,@firstDate) and DATEADD(MONTH, 1 @firstDate) and schedule ='1st' then DATEADD(MONTH, 1 @firstDate)
end
as next_bill_run_date 
from your_table

答案 1 :(得分:1)

是的,您的逻辑是正确的。将case语句与SQL SERVER中的某些DATE函数一起使用。据我对SQL SERVER日期函数的了解有限,我对以下查询进行了构架。您仍然可以对此进行优化。

SELECT   
   RUN_DATE,SCHEDULE,
   case 
   when (DATEPART(month,run_date)=month(sysdatetime()) --checking same month
   and DATEPART(day, run_date) between 2 and 15 and Schedule='15th') --checking date between 2nd and 15th and schedule is 15th
   then DATEADD(month, DATEDIFF(month, 0,run_date), 0)+14  --selecting 15th of same month

   when (DATEPART(month,run_date)=month(sysdatetime()) 
   and DATEPART(day, run_date) between 2 and 15 and Schedule='1st') --checking date between 2nd and 15th and schedule is 1st
   then DATEADD(month, DATEDIFF(month, 0,run_date)+1, 0) --selecting 1st of next month

   when (DATEPART(month,run_date)=month(sysdatetime()) or run_date=DATEADD(month, DATEDIFF(month, 0,run_date)+1,0)) 
   and (((DATEPART(day, run_date) between 16 and 31) or (run_date=DATEADD(month, DATEDIFF(month, 0,run_date)+1,0))) 
   and Schedule='1st') 
   then case when (run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0)) 
             then
             DATEADD(month, DATEDIFF(month, 0,run_date),0) -- if 1st of next month, select first day of same month
             else
             DATEADD(month, DATEDIFF(month, 0,run_date)+1,0) --selecting 1st of next month
             end
   when (DATEPART(month,run_date)=month(sysdatetime()) or run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0)) 
   and (((DATEPART(day, run_date) between 16 and 31) or (run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0))) 
   and Schedule='15th') 
   then case when (run_date=DATEADD(month, DATEDIFF(month, 0,run_date),0)) 
             then
             DATEADD(month, DATEDIFF(month, 0,run_date),0)+14 -- if 1st of next month, select 15 of same month
             else
              DATEADD(month, DATEDIFF(month, 0,run_date)+1,0)+14 --selecting 15th of next month
             end
    end as NEXT_BILL_RUN_DATE
FROM mytable ;    

答案 2 :(得分:0)

case when schedule='1st' then DATEFROMPARTS(DATEPART(year, DATEADD(month, 1, RUN_DATE)), DATEPART(month, DATEADD(month, 1, RUN_DATE)), 01) when schedule='15th' and DATEPART(day, RUN_DATE)>=15 then DATEFROMPARTS(DATEPART(year, DATEADD(month, 1, RUN_DATE)), DATEPART(month, DATEADD(month, 1,RUN_DATE)), 15) when schedule='15th' and DATEPART(day, RUN_DATE)<15 then DATEFROMPARTS(DATEPART(year, RUN_DATE), DATEPART(month, RUN_DATE)), 15) end AS NEXT_BILL_RUN_DATE