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

问题描述 投票:0回答:2

需要帮助为现有表创建视图,该视图中有一个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

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

sql-server view
2个回答
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

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

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


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

我希望我能这样更清楚地阐明

© www.soinside.com 2019 - 2024. All rights reserved.