2016-03-13 145 views
0

我有一个包裹表,其中每个包包含天数,包括天数[任意一天星期日,星期一,...]查找结束日期基于开始日期和持续时间 - T-SQL

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 

当客户选择任何包裹(选择开始日期)时,我需要根据编号计算包裹的到期日期。包中包含的天数和天数。

我需要创建一个函数,其中将返回到期日期提供 以下3个输入。

  1. 开始日期
  2. 被包括天
  3. 天数

例子:

对于包1,从3月13-2016开始,正确的结束日期应该是: 03-Apr-2016 (10天将是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) 

到目前为止,我已经做到了这一点,但它包括所有的7天。

任何人都可以帮助只有特定的日子可以包括以获得正确的失效日期?

+0

请解释* Days Included *的工作原理 – har07

+0

另外,发布正确的' EndDate'示例给出了某个'StartDate','NoDays'和* Days Included * – har07

+0

@ har07我编辑了一个样本的问题。询问我是否仍不清楚 –

回答

1

您可以用数字表,万年历表做到这一点,我创建了使用您packagedays表的规范化版本的一些测试数据。

---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 [email protected]) and date>[email protected] 
) 
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 [email protected]) 

return @expiry 
end 

,如果你不想改变daysincluded归一化版本,你可能必须使用符合功能,做同样和CTE它添加

你可以看到日历表here

+0

基本上我有规范化的表,我在这里提到只是为了更好的理解,谢谢,让我试试你的解决方案 –

+0

你需要先运行我的解决方案之前创建日历表 – TheGameiswar

+0

http://www.sqlservercentral .com/blogs/dwainsql/2014/03/30/calendar-tables-in-t-sql/ – TheGameiswar

1
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 

,如果你想要的功能dbo.splitstring,请点击here

+0

我没有在期满计算中包含当天,所以如果你想包括这个,那么在我需要的IF块 – Hasham

+0

之后放置语句SET @ EndDate = DATEADD(DD,1,@ EndDate)只有到期日的回报:( –

1
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 

要查看ConvertCsvToInt函数click here

相关问题