Смена SQL Server по будням, выходным, праздничным дням и времени суток - PullRequest
0 голосов
/ 19 октября 2019

Нужна помощь в создании представления для существующей таблицы, в которой есть столбец datetime, и он должен быть разделен на смены в зависимости от дня недели, часа дня. Например, в будние дни смены должны быть между 6, 15 и 24, я имею в виду ночные смены от 0 до 6, с 6 до 15 утра и т. Д.

В Excel я сделал с вложенными if, и язнаю, как сделать это с несколькими случаями, когда заявления.

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 голосов
/ 19 октября 2019

Простой способ - просто раскладывание регистра .... когда .... затем ... завершается следующим образом:

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

Но было бы более элегантно использовать вместо скалярных функций, в порядке vtoизбегайте повторяющихся паттернов.

0 голосов
/ 20 октября 2019

Другой способ увидеть это - использовать вместо этого скалярную функцию, как показано ниже.

Сначала давайте создадим функцию, которая будет возвращать имя смены в соответствии с началом утренней смены времени и когда она заканчивается

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

Надеюсь, я прояснил это таким образом

0 голосов
/ 19 октября 2019

Вместо сложных инструкций я рекомендую использовать таблицу для дней и смен.

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
...