简体   繁体   中英

Find End Date based on Start date and Duration - T-SQL

I have a table for packages, where each package consists of Number of Days, Days included [any day(s) Sunday, Monday, ... ]

Package   | Duration | Days Included
-------------------------------------------
Package 1 | 10 days | '1,2,3' [Sun, Mon, Tue] 
Package 2 | 15 days | '4,5,6,7' [Wed, Thu, Fri, Sat]
Package 3 | 30 days | '1,2,3,4,5,6,7' [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
etc

When customer selects any package (selecting the start date), I need to calculate the expiry date of that package based on the no. of days and days included in that package.

I need to create a function in which will return the Expiry Date providing the following 3 inputs.

  1. Start date
  2. Number of days
  3. Days to be included

Example:

For Package 1, starting from 13-Mar-2016, Correct End Date should be: 03-Apr-2016 (10 days would be 13,14,15,20,21,22,27,28,29 March, 03 Apr)

 DECLARE @StartDate DATETIME
 DECLARE @NoDays INT
 DECLARE @EndDate DATETIME
 SET @EndDate = DATEADD(DD, @NoDays, @StartDate)

So far I have done this, but it is including all 7 days.

Can anybody help how only the specific days can be included to get the correct expiry date?

DECLARE @StartDate DATETIME
DECLARE @NoDays INT
DECLARE @DaysIncluded VARCHAR(20)
DECLARE @EndDate DATETIME, @LOOP INT, @Count int

SET @StartDate = getdate()
SET @NoDays = 10
SET @DaysIncluded = '1,2'
SET @LOOP = @NoDays


SET @EndDate = @StartDate

WHILE (@LOOP > 0)
BEGIN

SET @EndDate = DATEADD(DD, 1, @EndDate)
print @EndDate
Select @Count = Count(1) from dbo.splitstring(@DaysIncluded) where name in (DATEPART(dw,@EndDate))

if(@Count > 0)
BEGIN
print 'day added'
SET @LOOP = @LOOP - 1
END

END

if you want the function dbo.splitstring, please click here

You can do it with Numbers table and calendar table,i have created some test data which uses normalized version of your packagedays table.

---package table
create table packagetable
(
id int,
maxduration int
)


insert into packagetable
select 1,10


----storing number of days in normalized way
create table packagedays
(
pkgid int,
pkgdays int
)

insert into packagedays
select 1,1
union all
select 1,2

create function dbo.getexpirydate
(
@packageno int,
@dt datetime
)
returns datetime
as
begin

declare @expiry datetime
;with cte
as
(
select date,row_number() over ( order by date) as rn from dbo.calendar 
where wkdno in (select pkgdays from packagedays where pkgid=@packageno ) and date>=@dt
)
select @expiry= max(Date)+1--after last date of offer add +1 to get next day as expiry date
from cte
where rn=(select maxduration from packagetable where id=@packageno)

return @expiry
end

if you don't want alter daysincluded as normalized version,you might have to use tally function which does the same and add it in cte

You can see calendar table here

DECLARE @StartDate DATETIME = '3/13/2016'
DECLARE @NoDays INT = 10
DECLARE @DaysIncluded varchar(50) = '1,2,3,4'

DECLARE @EndDate DATETIME = DATEADD(d, -1, @StartDate)

DECLARE @IndexOuter INT = 1
DECLARE @IndexInner INT = 1
DECLARE @AuxDate DATETIME

while @IndexOuter <= @NoDays
begin

    set @IndexInner = 1

    while @IndexInner <= 7
    begin
        SET @AuxDate = DATEADD(d, @IndexInner, @EndDate)

        IF DATEPART(DW, @AuxDate) in (select IntValue from ConvertCsvToInt(@DaysIncluded))  
        begin
            set @EndDate = @AuxDate
            break
        end

        set @IndexInner = @IndexInner + 1
    end

    print @EndDate

    set @IndexOuter = @IndexOuter + 1
end

select @EndDate

To see ConvertCsvToInt function click here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM