Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基于开始日期和持续时间查找结束日期-T-SQL_Sql_Sql Server_Tsql_Date - Fatal编程技术网

基于开始日期和持续时间查找结束日期-T-SQL

基于开始日期和持续时间查找结束日期-T-SQL,sql,sql-server,tsql,date,Sql,Sql Server,Tsql,Date,我有一个包裹表,其中每个包裹包括天数,包括天数[周日、周一等任何一天] 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,

我有一个包裹表,其中每个包裹包括天数,包括天数[周日、周一等任何一天]

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,从2016年3月13日开始,正确的结束日期应为: 2016年4月3日 (10天为2003年3月13、14、15、20、21、22、27、28、29日 四月)

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

    有人能帮助我们如何只包括特定的天数来获得正确的到期日吗

    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,请单击


    如果您想要函数dbo.splitstring,请单击

    您可以使用数字表和日历表,我已经创建了一些使用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 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
    
    如果您不想将alterdaysincluded作为规范化版本,那么您可能必须使用tally函数,该函数也可以这样做,并将其添加到cte中


    您可以看到日历表

    您可以使用数字表和日历表,我已经创建了一些测试数据,使用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 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
    
    如果您不想将alterdaysincluded作为规范化版本,那么您可能必须使用tally函数,该函数也可以这样做,并将其添加到cte中

    您可以查看日历表

    DECLARE@StartDate DATETIME='3/13/2016'
    声明@NoDays INT=10
    声明@DaysIncluded varchar(50)='1,2,3,4'
    声明@enddatetime=DATEADD(d,-1,@StartDate)
    声明@IndexOuter INT=1
    声明@IndexInner INT=1
    声明@AuxDate DATETIME
    而@IndexOuter
    DECLARE@StartDate DATETIME='3/13/2016'
    声明@NoDays INT=10
    声明@DaysIncluded varchar(50)='1,2,3,4'
    声明@enddatetime=DATEADD(d,-1,@StartDate)
    声明@IndexOuter INT=1
    声明@IndexInner INT=1
    声明@AuxDate DATETIME
    
    请在@IndexOuter中解释天数是如何工作的,并给出一个正确的
    EndDate
    示例,给出特定的
    StartDate
    NoDays
    ,以及天数Included@har07我用一个样本编辑了这个问题。询问我是否仍不清楚请解释天数是如何包含的,并给出一个正确的
    结束日期
    示例,给出特定的
    开始日期
    节点日期
    ,以及天数Included@har07我用一个样本编辑了这个问题。问我是否仍然不清楚我有标准化的表,我在这里提到只是为了更好地理解。谢谢让我试试你的解决方案在运行我的解决方案之前,你需要先创建日历表。我认为这种逻辑比while循环(在其他答案中)更好。然而,日历表的创建是唯一的额外工作。是的,我们必须创建一次,这是无效的基本上我有规范化的表,我在这里提到只是为了更好地理解。谢谢让我试试你的解决方案在运行我的解决方案之前,你需要先创建日历表。我认为这种逻辑比while循环(在其他答案中)更好。但是,日历表的创建是唯一的额外工作。是的,我们必须创建一次,而且它是无效的。我没有在到期计算中包括当天,因此如果您想包括这一天,请将语句SET@EndDate=DATEADD(DD,1,@EndDate)放在if块之后,我只需要到期日期作为回报:(我没有将当前日期包括在到期计算中,因此如果您想将其包括在内,请将语句集@EndDate=DATEADD(DD,1,@EndDate)放在if块之后,作为回报,我只需要到期日期:(
    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