Найти смену сотрудника по названию даты в диапазоне дат - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть три таблицы, следующие:

Таблица HrShift:

Id  ShiftName       DaysOfWeek                                          StartTime   EndTime     StartDate   EndDate
1   Day Shift-1     Sunday,Monday,Tuesday,Wednesday,Thursday,Friday     09:00 AM    06:00 PM    2016-01-01  NULL
2   Day Shift-2     Sunday,Monday,Tuesday,Wednesday,Thursday,Friday     10:00 AM    07:00 PM    2010-01-01  NULL
3   Day Shift-3     Sunday,Monday,Tuesday,Wednesday,Thursday,Friday     11:00 AM    08:00 PM    2010-01-01  NULL

Таблица ShiftType:

Id  Name
1   Primary
2   Roster

Таблица EmployeeShifts:

Id  EmpId   HrShiftId   ShiftTypeId     StartDate   EndDate 
1   1       1           1               2018-01-01  NULL    
2   1       2           2               2018-02-01  2018-02-01
3   2       1           1               2018-01-01  NULL
4   2       2           2               2018-02-01  2018-02-01
5   2       3           2               2018-02-01  2018-02-01

Команды создания таблицы:

CREATE TABLE [HrShifts](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ShiftName] [nvarchar](max) NULL,
    [DaysOfWeek] [nvarchar](max) NULL,
    [StartTime] [nvarchar](max) NULL,
    [EndTime] [nvarchar](max) NULL,
    [StartDate] [datetime] NOT NULL,
    [EndDate] [datetime] NULL);

CREATE TABLE [ShiftType](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL);

CREATE TABLE [EmployeeShifts](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [EmpId] [int] NOT NULL,
    [HrShiftId] [int] NOT NULL,
    [ShiftTypeId] [int] NOT NULL,
    [StartDate] [datetime] NOT NULL,
    [EndDate] [datetime] NULL);

Мне нужно найти одну назначенную смену для каждого сотрудника между двумя датами.Список ShiftType получит приоритет над Первичным.Необходимо проверить столбец DaysOfWeek в таблице HrShift, который должен совпадать по имени дня для даты.

Ожидаемый результат между (2018-01-31 и 2018-2-2) следующий

Date        EmpId   ShiftType   HrShiftId   ShiftName       StartTime   EndTime
2018-01-31  1       1           1           Day Shift-1     09:00 AM    06:00 PM
2018-02-01  1       2           2           Day Shift-2     10:00 AM    07:00 PM
2018-02-02  1       1           1           Day Shift-1     09:00 AM    06:00 PM
2018-01-31  2       1           1           Day Shift-1     09:00 AM    06:00 PM
2018-02-01  2       2           2           Day Shift-2     10:00 AM    07:00 PM
2018-02-02  2       2           3           Day Shift-3     11:00 AM    08:00 PM

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Сначала вам нужно сгенерировать дни.Для этого вы можете использовать рекурсивный CTE (или календарную таблицу) или аналогичный метод.

with days as (
      select convert(date, '2018-01-31') as dte
      union all
      select dateadd(day, 1, dte)
      from days
      where dte < '2018-02-02'
     )
select d.dte, es.*, hs.startTime, hs.endTime
from EmployeeShifts es join
     HrShift hs
     on es.HrShiftId = hs.id cross join
     days d
where d.dte >= hs.startDate and
      (d.dte < hs.endDate or hs.endDate is null) and
      hs.daysofweek like '%' + datename(weekday, d.dte) + '%';

Я думаю, что предложение where охватывает всю необходимую логику сопоставления между датой и расписанием.

0 голосов
/ 02 февраля 2019

Я изменил несколько значений данных, чтобы показать вам разные результаты: измените имена временных переменных вместе со своими.

здесь я сначала делаю список дат @S_Date и @E_Date являются входными данными:

    DECLARE @S_Date AS DATETIME
    DECLARE @E_Date AS DATETIME
    DECLARE @TotalDays AS INT
    DECLARE @DisplayDate AS VARCHAR(50)
    DECLARE @WDN AS INT
    DECLARE @WDName AS VARCHAR(20)

    SET @S_Date =CONVERT(datetime,'01/31/2019')
    SET @E_Date =CONVERT(datetime,'02/02/2019')
    SET @WDN = DATEPART(WEEKDAY,@S_Date)
    SET @WDName = DATENAME(weekday,@S_Date)
    SET @TotalDays = DATEDIFF(dd,@S_Date, DATEADD(dd,1,@E_Date))
    SET @DisplayDate =  DATENAME(weekday, @S_Date)+' ' + DATENAME(dd,@S_Date)+' '+ DATENAME(m, @S_Date)+' '+ DATENAME(yy, @S_Date)


    CREATE TABLE #Monthdaytable(
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [DisplayDate] [varchar](50) NULL,
        [Actualdate] [datetime] NULL,
        [Week_Day_Number] INT NULL,
        [Week_Day_Name] VARCHAR(20) NULL
    ) ON [PRIMARY]

    DECLARE @i AS INT
    SET @i = 1  
    WHILE(@i<=@TotalDays)
    BEGIN
        INSERT INTO #Monthdaytable
                ( DisplayDate, ActualDate ,Week_Day_Number, Week_Day_Name)
        VALUES  (@DisplayDate, @S_Date, @WDN, @WDName)
        SET @S_Date = DATEADD(dd,1,@S_Date)
        SET @WDN = DATEPART(WEEKDAY,@S_Date)
        SET @WDName = DATENAME(weekday,@S_Date)
        SET @DisplayDate =DATENAME(weekday, @S_Date)+' ' + DATENAME(dd,@S_Date)+' '+  DATENAME(m, @S_Date)+' '+ DATENAME(yy, @S_Date)
        SET @i = @i+1
    END

Только ваши таблицы:

    CREATE TABLE #HrShift (Id int, ShiftName varchar(50), DaysOfWeek varchar(500),StartTime time(7),EndTime time(7), StartDate datetime, EndDate datetime)

INSERT INTO #HrShift ( Id,  ShiftName,       DaysOfWeek, StartTime,   EndTime,     StartDate,   EndDate) VALUES (1,   'Day Shift-1',     'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday' ,    '09:00 AM' ,   '06:00 PM',    '2016-01-01' , NULL)
INSERT INTO #HrShift ( Id,  ShiftName,       DaysOfWeek, StartTime,   EndTime,     StartDate,   EndDate) VALUES (2,  'Day Shift-2' ,  'Sunday,Monday,Tuesday,Wednesday,Thursday'   ,  '10:00 AM'   , '07:00 PM' ,   '2010-01-01' , NULL)
INSERT INTO #HrShift ( Id,  ShiftName,       DaysOfWeek, StartTime,   EndTime,     StartDate,   EndDate) VALUES (3,   'Day Shift-3' ,  'Sunday,Monday,Tuesday,Wednesday,Thursday' ,    '11:00 AM'   , '08:00 PM' ,   '2010-01-01' , NULL)

    CREATE TABLE #ShiftType (Id int,  Name varchar(50))


INSERT INTO #ShiftType(Id,  Name) VALUES (1,   'Primary')
INSERT INTO #ShiftType(Id,  Name) VALUES (2,   'Roster')

CREATE TABLE #EmployeeShifts (Id int,  EmpId int,   HrShiftId int,  ShiftTypeId int,    StartDate datetime,   EndDate datetime)


INSERT INTO #EmployeeShifts(Id,  EmpId,   HrShiftId,   ShiftTypeId,     StartDate,   EndDate ) VALUES(1,   1,       1,           1,               '2018-01-01',  NULL    )
INSERT INTO #EmployeeShifts(Id,  EmpId,   HrShiftId,   ShiftTypeId,     StartDate,   EndDate ) VALUES(2,   1,       2,           2,               '2018-02-01',  '2018-02-01')
INSERT INTO #EmployeeShifts(Id,  EmpId,   HrShiftId,   ShiftTypeId,     StartDate,   EndDate ) VALUES(3,   2,       1,           1,               '2018-01-01',  NULL)
INSERT INTO #EmployeeShifts(Id,  EmpId,   HrShiftId,   ShiftTypeId,     StartDate,   EndDate ) VALUES(4,   2,       2,           2,               '2018-02-01',  '2019-02-05')
INSERT INTO #EmployeeShifts(Id,  EmpId,   HrShiftId,   ShiftTypeId,     StartDate,   EndDate ) VALUES(5,   2,       3,           2,               '2018-02-01',  '2019-02-01')


    SELECT * FROM #Monthdaytable 
    --SELECT * FROM #HrShift
    --SELECT * FROM #ShiftType
    --SELECT * FROM #EmployeeShifts

Это запрос, который вынужно:

SELECT m.DisplayDate ,EmpId,ShiftName,t.Name,StartTime,EndTime
        FROM #EmployeeShifts e INNER JOIN
                #ShiftType t ON  e.ShiftTypeId = t.Id INNER JOIN
                #HrShift s ON s.Id = e.HrShiftId INNER JOIN
                #Monthdaytable m ON 1 = 1
        WHERE CONVERT(varchar,m.Actualdate,112)>=CONVERT(varchar,e.StartDate,112)
                and  CONVERT(varchar,m.Actualdate,112)<=CONVERT(varchar,ISNULL(e.EndDate, m.Actualdate),112)            
                and s.DaysOfWeek  LIKE '%'+m.Week_Day_Name+'%' 

для понижения температуры

    DROP TABLE #EmployeeShifts
    DROP TABLE #ShiftType
    DROP TABLE #HrShift
    DROP TABLE #Monthdaytable 
...