Reputation: 968
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.
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?
Upvotes: 0
Views: 1822
Reputation: 11
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
Upvotes: 1
Reputation: 28938
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
Upvotes: 1
Reputation: 34
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
Upvotes: 1