基于SQL Server班次的工作日,周末,公共假期和一天中的时间

时间:2019-10-19 16:46:14

标签: sql-server view

需要为现有表创建视图的帮助,该视图中有一个datetime列,并且必须根据星期几和一天中的小时将班次分为几班。例如,在工作日期间,班次应该在6、15和24之间,我的意思是从0到6夜班,从6到15上午,等等。

在Excel中,我已经使用了嵌套的ifs,但我不知道如何处理多种情况的when语句。

IF([Day]="Monday";IF(AND([Hour]>=6;[Hour]<14);"Morning";IF(AND([Hour]>=14;[Hour]<22);"Afternoon";"N"));
IF([Day]="Wednesday";IF(AND([Hour]>=6;[Hour]<14);"Morning";IF(AND([Hour]>=14;[Hour]<22);"Afternoon";"N"));
IF([Day]="Friday";IF(AND([Hour]>=6;[Hour]<14);"Morning";IF(AND([Hour]>=14;[Hour]<22);"Afternoon";"N")); 

ID Logtime             Shift
-------------------------------
1  2019-10-17 00:05:00 Night
2  2019-10-17 05:55:00 Night
3  2019-10-17 06:05:00 Morning
4  2019-10-17 14:55:00 Morning
5  2019-10-17 15:05:00 Evening
6  2019-10-17 23:55:00 Evening

我可以用以下代码完成一天,但是几天都不能。

case    
   when DATENAME(WEEKDAY, LogTime) = 'Thursday' and DATEPART(hour, LogTime) < 6  
      then 'Night'
   when DATENAME(WEEKDAY, LogTime) = 'Thursday' and DATEPART(hour, LogTime) >= 6 and DATEPART(hour, logtime) < 15 
      then 'Morning' 
   else 'Evening'
end as Shift

我希望有人能够提供帮助,并在此先多谢。

3 个答案:

答案 0 :(得分:0)

我建议您使用表格来代替天数和班次。

DECLARE @SampleData TABLE (ID INT, Logtime  DATETIME)
INSERT INTO @SampleData VALUES
(1, '2019-10-17 00:05:00'),
(2, '2019-10-17 05:55:00'),
(3, '2019-10-17 06:05:00'),
(4, '2019-10-17 14:55:00'),
(5, '2019-10-17 15:05:00'),
(6, '2019-10-17 23:55:00')


SET DATEFIRST  1

SELECT T.*, Shifts.Shift FROM 
    @SampleData T
    INNER JOIN (VALUES ( 1, 0,  6,'Night'), ( 1, 6,  15,'Morning'), ( 1, 15, 24,'Evening'),
                       ( 2, 0,  6,'Night'), ( 2, 6,  15,'Morning'), ( 2, 15, 24,'Evening'),
                       ( 3, 0,  6,'Night'), ( 3, 6,  15,'Morning'), ( 3, 15, 24,'Evening'),
                       ( 4, 0,  6,'Night'), ( 4, 6,  15,'Morning'), ( 4, 15, 24,'Evening'),
                       ( 5, 0,  6,'Night'), ( 5, 6,  15,'Morning'), ( 5, 15, 24,'Evening'),
                       ( 6, 0,  6,'Night'), ( 6, 6,  15,'Morning'), ( 6, 15, 24,'Evening'),
                       ( 7, 0,  6,'Night'), ( 7, 6,  15,'Morning'), ( 7, 15, 24,'Evening') ) Shifts(DayOfW, SDate, EDate, Shift) ON 
                                                                DATEPART(WEEKDAY,T.Logtime) = Shifts.DayOfW
                                                            AND DATEPART(HOUR,T.Logtime) >= Shifts.SDate 
                                                            AND DATEPART(HOUR,T.Logtime) < Shifts.EDate

结果:

ID          Logtime                 Shift
----------- ----------------------- -------
1           2019-10-17 00:05:00.000 Night
2           2019-10-17 05:55:00.000 Night
3           2019-10-17 06:05:00.000 Morning
4           2019-10-17 14:55:00.000 Morning
5           2019-10-17 15:05:00.000 Evening
6           2019-10-17 23:55:00.000 Evening

答案 1 :(得分:0)

简单的方法只是嵌套大小写....当....然后...结束如下:

case DATENAME(WEEKDAY, @LogTime)
when 'Monday'  then case when DATEPART(hour, @LogTime)  < 6 then 'Night'
                          when DATEPART(hour, @LogTime) >= 6 and 
                               DATEPART(hour, @LogTime) < 15 then 'Morning' 
                                                             else 'Evening'
                     end
when 'Tuesday' then case when DATEPART(hour, @LogTime)  < 6 then 'Night'
                          when DATEPART(hour, @LogTime) >= 6 and 
                               DATEPART(hour, @LogTime) < 15 then 'Morning' 
                                                             else 'Evening'
                     end
when 'Wednesday' then case when DATEPART(hour, @LogTime)  < 6 then 'Night'
                          when DATEPART(hour, @LogTime) >= 6 and 
                               DATEPART(hour, @LogTime) < 15 then 'Morning' 
                                                             else 'Evening'
                     end
when 'Thursday' then case when DATEPART(hour, @LogTime)  < 6 then 'Night'
                          when DATEPART(hour, @LogTime) >= 6 and 
                               DATEPART(hour, @LogTime) < 15 then 'Morning' 
                                                             else 'Evening'
                     end
when 'Friday' then case when DATEPART(hour, @LogTime)  < 6 then 'Night'
                          when DATEPART(hour, @LogTime) >= 6 and 
                               DATEPART(hour, @LogTime) < 15 then 'Morning' 
                                                             else 'Evening'
                     end
             else 'weekend'
end

但是,为了避免重复模式,使用标量函数代替标量函数会更优雅。

答案 2 :(得分:0)

另一种查看方式是使用标量函数,如下所示

首先让我们创建一个返回班次名称的函数 根据早上上班的开始时间和结束时间

IF OBJECT_ID ('ufn_DayPart', 'FN') IS NOT NULL
    DROP FUNCTION ufn_DayPart;
GO
CREATE FUNCTION ufn_DayPart(
    @LogTime datetime, 
    @MorningShiftStart int, 
    @MorningShiftEnd int)
RETURNS 
    VARCHAR(10)AS
BEGIN
    RETURN CASE WHEN DATEPART(hour, @LogTime)  < @MorningShiftStart then 'Night'
                WHEN DATEPART(hour, @LogTime) >= @MorningShiftStart and 
                     DATEPART(hour, @LogTime) <  @MorningShiftEnd   then 'Morning' 
                                                                    else 'Evening'
           END
END
GO

现在将其放在一个星期的角度来看 让我们创建一个函数,其中移位可以开始或结束 在不同的时间(取决于星期几)

IF OBJECT_ID ('ufn_GetShift', 'FN') IS NOT NULL
    DROP FUNCTION ufn_GetShift;
GO

CREATE FUNCTION ufn_GetShift(
    @LogTime datetime)
RETURNS 
    VARCHAR(10)AS
BEGIN
    RETURN case DATENAME(WEEKDAY, @LogTime)
                when 'Monday'    then dbo.ufn_DayPart(@LogTime, 6, 15 )
                when 'Tuesday'   then dbo.ufn_DayPart(@LogTime, 6, 15 )
                when 'Wednesday' then dbo.ufn_DayPart(@LogTime, 6, 15 )
                when 'Thursday'  then dbo.ufn_DayPart(@LogTime, 6, 15 )
                when 'Friday'    then dbo.ufn_DayPart(@LogTime, 6, 15 )
                                 else 'weekend'
                END
END
GO

现在,让我们在非常简单的查询中尝试一下:

begin
declare @LogTime as datetime
set @LogTime = '2019-09-29 01:10'    SELECT @LogTime, dbo.ufn_GetShift(@LogTime) as shift
set @LogTime = '2019-09-30 20:10'    SELECT @LogTime, dbo.ufn_GetShift(@LogTime) as shift
set @LogTime = '2019-10-01 12:10'    SELECT @LogTime, dbo.ufn_GetShift(@LogTime) as shift
set @LogTime = '2019-10-02 06:00'    SELECT @LogTime, dbo.ufn_GetShift(@LogTime) as shift
set @LogTime = '2019-10-02 05:59:59' SELECT @LogTime, dbo.ufn_GetShift(@LogTime) as shift
set @LogTime = '2019-10-03 19:10'    SELECT @LogTime, dbo.ufn_GetShift(@LogTime) as shift
end

在您的查询中,它看起来像:

SELECT col_1, col_2, dbo.ufn_GetShift(col_timeLog) as shift
FROM YourTable

我希望我能通过这种方式更清楚