0

我需要创建一个临时表,该表将基于输入参数 sdate 和 edate 具有 Start_Date 和 End_Date 列。此表是办公室的非工作时间列表,包括工作日下午 6 点至早上 6 点。周末我需要时间如下:

  1. 周五下午 6 点至周六凌晨 12 点
  2. 周六上午 12 点至周日上午 12 点和
  3. 周日上午 12 点至周一上午 6 点

希望下表能让您了解我想要实现的目标:

开始 开始日期 结尾 结束日期
太阳 08/01/2021 00:00:00.000 星期一 2021 年 8 月 2 日 06:00:00.000
星期一 2021 年 8 月 2 日 18:00:00.000 周二 2021 年 8 月 3 日 06:00:00.000
周二 2021 年 8 月 3 日 18:00:00.000 星期三 2021 年 8 月 4 日 06:00:00.000
星期三 2021 年 8 月 4 日 18:00:00.000 周四 2021 年 8 月 5 日 06:00:00.000
周四 2021 年 8 月 5 日 18:00:00.000 周五 2021 年 8 月 6 日 06:00:00.000
周五 2021 年 8 月 6 日 18:00:00.000 星期六 08/07/2021 00:00:00.000
星期六 08/07/2021 00:00:00.000 太阳 2021 年 8 月 8 日 00:00:00.000
太阳 2021 年 8 月 8 日 00:00:00.000 星期一 2021 年 8 月 9 日 06:00:00.000
星期一 2021 年 8 月 9 日 18:00:00.000 周二 2021 年 8 月 10 日 06:00:00.000
周二 2021 年 8 月 10 日 18:00:00.000 星期三 2021 年 8 月 11 日 06:00:00.000

我已经尝试了以下代码,但它没有得到正确的时间范围。

ALTER PROCEDURE [dbo].[temptableforoffhours]
    @BDate  varchar(50),
    @EDate   varchar(50),
    @Provider   varchar(1000)=''

AS

BEGIN
SET NOCOUNT ON
    
DECLARE 
    @BeginDate  datetime = '',
    @EndDate    DATETIME = ''

    IF @BeginDate = '' AND @EndDate = ''
    BEGIN 
        SET @BeginDate = DATEADD(YY,-3,GETDATE())
        SET @EndDate = GETDATE()
    END

    IF @BeginDate <> '' AND @EndDate <> ''
    BEGIN
        
        Set @BeginDate =CONVERT(datetime, @BDate, 121)
        
        SET @EndDate =Convert (Datetime, cast(CONVERT(DateTime, DATEADD(DD,1,@EDate), 121) as Date),121)
        

    END

/********************************Creation of #tmptimeFrameAudit table with FrameID and Start_day and end_Day********************************/

Declare @CountTimeFrames int = DateDiff(Day, @BeginDate, @EndDate)


DECLARE @Counter INT
SET @Counter = 1

Create Table #tmptimeFrameAudit (Frameid int,Start_Day datetime, End_Day datetime, doW varchar(10))

WHILE ( @Counter <= @CountTimeFrames)
BEGIN

IF @counter = 1
Begin
    set @BeginDate = @BeginDate
End
Else
Begin
    set @BeginDate = DATEADD(DD,1,@BeginDate)
End

IF (DatePart(weekday,@BeginDate) = 7)
        BEGIN
            Insert Into #tmptimeFrameAudit values (@Counter,@BeginDate,DATEADD(HOUR,24,@BeginDate),  DATENAME(WEEKDAY,@BeginDate))
        END
ELSE IF (DatePart(weekday,@BeginDate) = 6) 
        BEGIN
            Insert Into #tmptimeFrameAudit values (@Counter,Dateadd(HOUR,18,CONVERT(datetime, @BeginDate, 121)),DATEADD(HOUR,6,@BeginDate),  DATENAME(WEEKDAY,@BeginDate))
        END
ELSE IF (DatePart(weekday,@BeginDate) = 1) 
        BEGIN
            Insert Into #tmptimeFrameAudit values (@Counter,@BeginDate,DATEADD(HOUR,30,@BeginDate),  DATENAME(WEEKDAY,@BeginDate))
        END
ELSE  
        BEGIN
            Insert Into #tmptimeFrameAudit values (@Counter,Dateadd(HOUR,18,CONVERT(datetime, @BeginDate, 121)),DATEADD(HOUR,12,@BeginDate),  DATENAME(WEEKDAY,@BeginDate))
        END     

set @Counter = @Counter+1

END

Select * from #tmptimeFrameAudit

drop Table #tmptimeFrameAudit

END

你能告诉我代码有什么问题并帮助我纠正它吗?谢谢!

4

2 回答 2

1

我还建议一个日历表,这是我日历表的一小部分

select c.CalendarID,
       c.DateCalendar,
       c.DayNameID,
       c.DayName,
       c.IsWeekDay
from   tblCalendar c
where  DateCalendar between '20210801' and '20210810'

CalendarID DateCalendar DayNameID DayName   IsWeekDay
2770       2021-08-01   7         Sunday    False
2771       2021-08-02   1         Monday    True
2772       2021-08-03   2         Tuesday   True
2773       2021-08-04   3         Wednesday True
2774       2021-08-05   4         Thursday  True
2775       2021-08-06   5         Friday    True
2776       2021-08-07   6         Saturday  False
2777       2021-08-08   7         Sunday    False
2778       2021-08-09   1         Monday    True
2779       2021-08-10   2         Tuesday   True

它从我的公司开始的地方开始,直到 2100 年

有了这个,您的预期结果很容易实现

select 
       c.DayName,
       case when DayNameID in (6, 7) then c.DateCalendar
            else dateadd(hour, 18, convert(datetime,c.DateCalendar))
       end as start_Date,
       case when DayNameID = 7 then dateadd(hour, 6, convert(datetime,c.DateCalendar))
            when DayNameID in (5, 6) then dateadd(hour, 24, convert(datetime,c.DateCalendar))
            else dateadd(hour, 30, convert(datetime,c.DateCalendar))
       end as end_Date
       
from   tblCalendar c
where  c.DateCalendar between '20210801' and '20210810'

它返回这个

DayName    start_Date          end_Date
Sunday     01/08/2021 00:00:00  01/08/2021 06:00:00
Monday     02/08/2021 18:00:00  03/08/2021 06:00:00
Tuesday    03/08/2021 18:00:00  04/08/2021 06:00:00
Wednesday  04/08/2021 18:00:00  05/08/2021 06:00:00
Thursday   05/08/2021 18:00:00  06/08/2021 06:00:00
Friday     06/08/2021 18:00:00  07/08/2021 00:00:00
Saturday   07/08/2021 00:00:00  07/08/2021 00:00:00
Sunday     08/08/2021 00:00:00  08/08/2021 06:00:00
Monday     09/08/2021 18:00:00  10/08/2021 06:00:00
Tuesday    10/08/2021 18:00:00  11/08/2021 06:00:00

我发现有这样一张桌子为我解决了很多问题,它也可以为你做同样的事情

于 2021-09-23T05:53:21.330 回答
1

不确定我是否理解您的 Provider 参数的意义。它根本没有在您的代码中引用。我还强烈建议您传递正确的数据类型而不是字符串。

我建议使用日历表是一种更好的方法,因为您可以灵活地处理假期休假,甚至在某些日子延长或缩短工作时间。但这超出了您所要求的范围。

我在这里使用计数表而不是循环。我在我的数据库中保留一个作为这样的视图。

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally

现在我们可以利用这个计数表来解决这个问题。

create PROCEDURE [dbo].[temptableforoffhours]
(
    @BDate date
    , @EDate date
    , @Provider varchar(1000)=''
) as

    set nocount on;
        
    declare @StartDate datetime = @BDate 
        , @EndDate datetime = @EDate;

    with Dates as
    (
        select CurrentDate = dateadd(day, t.N - 1, @StartDate)
        from cteTally t
        where t.N <= datediff(day, @StartDate, @EndDate)
    )

    select Start = datename(weekday, d.CurrentDate)
        , Start_Date = dateadd(hour, case datename(weekday, d.CurrentDate) when 'Sunday' then 0 else 18 end, d.CurrentDate)
        , [End] = case datename(weekday, d.CurrentDate) when 'Friday' then dateadd(day, 1, d.CurrentDate) when 'Saturday' then dateadd(day, 1, d.CurrentDate) else dateadd(hour, 30, d.CurrentDate) end
        , End_Date = case datename(weekday, d.CurrentDate) when 'Friday' then dateadd(day, 1, d.CurrentDate) when 'Saturday' then dateadd(day, 1, d.CurrentDate) else dateadd(hour, 30, d.CurrentDate) end
    from Dates d;

这将返回您在问题中显示的结果。

exec temptableforoffhours @BDate = '20210801', @EDate = '20210811', @Provider = ''
于 2021-09-22T15:55:33.597 回答