目前正在使用SQL Server,我有一个表,其中登记了从登记日期开始的计划更改(空是员工休假)

问题是,当我try 取消透视表并连接日历表时,如果有两次或更多更改,它会复制这些值,它会复制从更改日期开始的值.

这是我目前为止所做的


`IF OBJECT_ID('tempdb..#ScheduleChange') Is Not Null Drop Table #ScheduleChange
Create table #ScheduleChange(ChangeDate Date, EmployeeId NVARCHAR(50), Monday NVARCHAR(50), Tuesday NVARCHAR(50), Wednesday NVARCHAR(50), Thursday NVARCHAR(50), Friday NVARCHAR(50), Saturday NVARCHAR(50), Sunday NVARCHAR(50))
INSERT INTO #ScheduleChange VALUES
('2024-01-02','100', '11:00 a.m.-7:00 p.m.', '11:00 a.m.-7:00 p.m.','11:00 a.m.-7:00 p.m.','11:00 a.m.-7:00 p.m.','11:00 a.m.-7:00 p.m.',NULL,'10:00 a.m.-2:00 p.m.'),
('2024-01-14','100','9:00 a.m-5:00 p.m','9:00 a.m-5:00 p.m','9:00 a.m-5:00 p.m','9:00 a.m-5:00 p.m','9:00 a.m-5:00 p.m',NULL,'10:00 a.m.-2:00 p.m.'),
('2024-01-04', '200','9:00 a.m.-5:00 p.m.','9:00 a.m.-5:00 p.m.','9:00 a.m.-5:00 p.m.','9:00 a.m.-5:00 p.m.','9:00 a.m.-5:00 p.m.','9:00 a.m.-1:00 p.m.',NULL),
('2024-01-10','200','10:00 a.m.-6:00 p.m.','10:00 a.m.-6:00 p.m.','10:00 a.m.-6:00 p.m.','10:00 a.m.-6:00 p.m.','10:00 a.m.-6:00 p.m.','10:00 a.m.-2:00 p.m.',NULL)


IF OBJECT_ID('tempdb..#Calendar') Is Not Null Drop Table #Calendar
Create table #Calendar(Date Date, WeekDayName NVARCHAR(15))
Declare @Start Date
Set @Start = '20240101'

WHILE @Start <= Cast(Getdate()-1 As Date)
BEGIN
  INSERT #Calendar
  Select @Start,
  DATENAME(DW,@Start)

 Set @Start =Dateadd(day,1,@Start)
End

;WITH
schedules
AS
(
    SELECT ChangeDate, EmployeeId, Schedule, WeekDayName
    FROM #ScheduleChange
    unpivot
    (
      Schedule
      for WeekDayName in (Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday)
    ) unpiv
)
    SELECT schedules.*, #Calendar.Date
    FROM schedules JOIN #Calendar ON #Calendar.date >= schedules.ChangeDate AND schedules.WeekDayName = #Calendar.WeekDayName
    ORDER BY schedules.EmployeeId, schedules.ChangeDate`

结果给了我从那一天开始的复制品.

有没有办法覆盖时间表,一旦有一个变化,从该日期向前,而不是复制一切?

推荐答案

您可以使用CROSS APPLY (SELECT TOP 1 ...)模式完成您想要的任务, for each 员工和日历日期组合 Select latest个适用的计划.

这将需要对查询进行一些重组,以提取不同的员工信息,将其交叉应用于日历,然后对于任何给定的员工/日期组合, Select 适当的计划行.

WITH schedules AS (
    SELECT ChangeDate, EmployeeId, Schedule, WeekDayName
    FROM #ScheduleChange
    unpivot
    (
      Schedule
      for WeekDayName in (Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday)
    ) unpiv
),
employees AS (
    SELECT DISTINCT EmployeeId
    FROM #ScheduleChange
)
SELECT E.EmployeeId, C.Date, S.WeekdayName, S.Schedule, S.ChangeDate
FROM employees E
CROSS JOIN #Calendar C
CROSS APPLY (
    SELECT TOP 1 *
    FROM schedules S
    WHERE S.EmployeeId = E.EmployeeId
    AND S.ChangeDate <= C.date
    AND S.WeekDayName = C.WeekDayName
    ORDER BY S.ChangeDate DESC
) S
ORDER BY
    S.EmployeeId, 
    C.Date,
    S.ChangeDate

结果:

EmployeeId Date WeekdayName Schedule ChangeDate
100 2024-01-02 Tuesday 11:00 a.m.-7:00 p.m. 2024-01-02
100 2024-01-03 Wednesday 11:00 a.m.-7:00 p.m. 2024-01-02
... ... ... ... ...
100 2024-01-11 Thursday 11:00 a.m.-7:00 p.m. 2024-01-02
100 2024-01-12 Friday 11:00 a.m.-7:00 p.m. 2024-01-02
100 2024-01-14 Sunday 10:00 a.m.-2:00 p.m. 2024-01-14
100 2024-01-15 Monday 9:00 a.m-5:00 p.m 2024-01-14
... ... ... ... ...
100 2024-01-29 Monday 9:00 a.m-5:00 p.m 2024-01-14
100 2024-01-30 Tuesday 9:00 a.m-5:00 p.m 2024-01-14
200 2024-01-04 Thursday 9:00 a.m.-5:00 p.m. 2024-01-04
200 2024-01-05 Friday 9:00 a.m.-5:00 p.m. 2024-01-04
200 2024-01-06 Saturday 9:00 a.m.-1:00 p.m. 2024-01-04
200 2024-01-08 Monday 9:00 a.m.-5:00 p.m. 2024-01-04
200 2024-01-09 Tuesday 9:00 a.m.-5:00 p.m. 2024-01-04
200 2024-01-10 Wednesday 10:00 a.m.-6:00 p.m. 2024-01-10
200 2024-01-11 Thursday 10:00 a.m.-6:00 p.m. 2024-01-10
... ... ... ... ...
200 2024-01-29 Monday 10:00 a.m.-6:00 p.m. 2024-01-10
200 2024-01-30 Tuesday 10:00 a.m.-6:00 p.m. 2024-01-10

请参见this db<>fiddle.

Sql相关问答推荐

在数据分区内执行确定

用于平均多个数据并与一个数据点进行比较以判断偏移量的SQL查询

解析键-值对,根据值 Select ,并使用SQL创建新列

在SQL中将相同且紧挨着的元素进行分组

SQL查询视图与连接?

获得第三名或最老的记录

有没有办法在Postgres中存储带有时区的时间戳,而不将其转换为UTC

动态组/转置

每个学校 Select N个最新的行,但跳过同一学生的重复行

Proc SQL Select Distinct SAS

获取分布在同一行的列中的出现次数

将二维数组的第一个和第二个元素取消嵌套到两个一维数组中

如何修复初学者 SQL INNER JOIN 查询错误

DB2 SQL查询结果多余数据

用替代方案替换 SQL Cursor 以提高性能

列(值不为空)到其他有序列

获取上个月和上一年的值

Postgresql:在链接表中判断相关表中插入值的条件

Postgresql 需要一个查询,为我提供所有没有具有特定状态值的子元素的父母

创建一个将层次 struct 级别放入列中的查询