【问题标题】:Employee Schedules for the next 2 weeks未来 2 周的员工计划
【发布时间】:2021-07-11 17:49:51
【问题描述】:

我目前正在处理几个 MySQL 事件,以发布未来 14 天的员工日程安排。

每个员工每天都有固定的时间表。我目前有一个包含时间表的表,但它没有日期,而是日期名称。下面是一个表格示例:

| ID |  EmpID   |   LOB  |    DOW    |   event  | StartAt   |    EndAt |
------------------------------------------------------------------------
| 1  |Z.Mora3847|  FNOL  |   Monday  |   Shift  |   9:00    |   17:30  |
| 2  |Z.Mora3847|  FNOL  |   Tuesday |   Shift  |   9:00    |   17:30  |
| 3  |Z.Mora3847|  FNOL  |  Wednesday|   Shift  |   9:00    |   17:30  |

我必须找到一种方法,根据该表中的星期几为每个员工生成接下来 2 周的时间表,并将其存储到一个类似的表中,在该表中,我们有一个名为“dow”的列,而不是列“日期”,它必须包含与第一个表中的日期名称匹配的未来日期。

如果我尝试这个,它会返回一天的预期值:

select SB.EmpID, SB.lob, dow, date_add(curdate(),interval 1 day) as Date, SB.StartAt, SB.EndAt from SandBox.ScheduleBase as SB where dayname(date_add(curdate(), interval 1 day)) = dow

这是输出:

| ID |  EmpID   | LOB  |  DOW      |  Date      | StartAt   |    EndAt |
------------------------------------------------------------------------
| 1  |Z.Mora3847|FNOL  | Saturday  | 2021-04-17 |   9:00    |   17:30  |

而且我希望能够在接下来的 14 天内做到这一点。

我正在使用 5.5.68-MariaDB

希望你们能帮我解决这个问题。

【问题讨论】:

  • 你尝试了什么?也许这有助于select now(), dayname(now()); 将输出今天的日期和今天的日期名称(“星期五”)。
  • 这是我尝试过的,它适用于一个日期:'select SB.EmpID, SB.lob, date_add(curdate(),interval 1 day), SB.event, SB.StartAt, SB .EndAt from SandBox.ScheduleBase as SB where dayname(curdate()) = dow' 但是我该如何获得接下来的 14 天?
  • 请将该信息添加到您的问题中(使用edit 功能)
  • 您使用的是哪个版本的 MySQL?您能否将其输出添加到问题中:SELECT @@VERSION;
  • 我刚刚更新了问题,感谢您的反馈。

标签: mysql


【解决方案1】:

首先,您需要将DOW 列替换为实际日期(假设我们将其命名为EventDate);您可以使用DAYOFWEEK() function 计算星期几:

SELECT DAYOFWEEK(EventDate);

此函数返回 1 代表星期日,2 代表星期一,依此类推(直到 7 代表星期六)。如果一周从星期一开始,并且您需要接下来的两个工作周(例如,星期天结束的一周),感谢from this post 的帮助,我们可以得到下星期一:

SELECT DATE_ADD(EventDate, INTERVAL (9 - IF(DAYOFWEEK(EventDate)=1, 8, DAYOFWEEK(CURDATE()))) DAY);

我们可以为此创建一个函数,以简化查询的编写:

-- Please check this in a database for real, I'm not sure if syntax is correct
DELIMITER $$

CREATE FUNCTION NEXTMONDAY(TargetDate DATE)
RETURNS DATE DETERMINISTIC
BEGIN
  DECLARE ResultDate DATE;
  SELECT DATE_ADD(TargetDate, INTERVAL (9 - IF(DAYOFWEEK(TargetDate)=1, 8, DAYOFWEEK(TargetDate))) DAY) INTO ResultDate;
  RETURN ResultDate;
END $$

DELIMITER ;

现在,通过使用此函数,我们可以将查询创建为:

SELECT *
  FROM ScheduleTable
  WHERE EmpId = '__employee id here__'
    AND EventDate BETWEEN NEXTMONDAY(CURDATE()) AND ADDDATE(NEXTMONDAY(CURDATE()), INTERVAL 13 DAY)

使用 13 天而不是 14 天将结束日(包括在内)设为星期日

抱歉,解释太长了,希望对您有所帮助。如果有什么你不能理解的,请告诉我;因为我的母语不是英语,所以我可能会犯错误。


EDIT 1(扩展答案):要获得一周中的实际名称(而不是数字),您需要使用内置函数DAYNAME。它接收DATE 并返回包含工作日名称的VARCHAR。如果您有 EventDate 列,则可以通过 DAYNAME(EventDate) 获取工作日名称。

【讨论】:

  • 这个解决方案似乎没问题。但是您错过了EventDate 字段不可用的一件事...
  • 我知道,这就是为什么我一开始就告诉他将DOW 列替换为EventDate 列,这样整个解决方案才有意义。当然,这不适用于经常性事件,但请确保尊重他要求的下两周。
  • 但是没有办法从 DayOfWeek 计算 EventDate。 Eventdate 计算 DayOfWeek 的另一种方法是可能的。
【解决方案2】:

从 SonicArg 扩展解决方案:

如果你这样做:

with recursive cte(x) as (
  select 0 as x 
  union all 
  select x+1 from cte where x<13) 
select * from cte;

你会得到从 0 到 13 的 14 个数字。

还有这个:

with recursive cte(x) as (
  select 0 as x 
  union all 
  select x+1 from cte where x<13) 
SELECT DATE_ADD(NEXTMONDAY(NOW()),INTERVAL cte.x DAY)
FROM cte;

将显示从下周一 ('2021-04-19') 到周日 ('2021-05-02') 的所有日期。

如果您将此与来自SonicARG 的查询结合使用,您将获得所需的结果。

我会把这个留给你,成功了!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-01
    • 2023-03-05
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多