【问题标题】:SQL Query that returns all missing months for date ranges within a year (MySQL Server)返回一年内日期范围内所有缺失月份的 SQL 查询 (MySQL Server)
【发布时间】:2023-02-22 04:36:39
【问题描述】:

不同部门雇用一名员工。例如,他们可能从事市场营销工作,并根据工作时间由部门 0001 和部门 0002 支付报酬。对于这个问题,时间并不重要,因为我真的只需要找到未雇用员工的日期范围。以下两名员工就是其中的例子。

Employee_ID Department_ID Start_Date End_Date
395961 0001 01/01/2022 03/31/2022
395961 0002 01/01/2022 01/31/2022
395961 0001 06/01/2022 10/31/2022
395961 0001 11/01/2022 12/31/2022
395962 0001 01/01/2022 03/31/2022
395962 0002 01/01/2022 01/31/2022
395962 0002 02/01/2022 04/30/2022
395962 0001 06/01/2022 10/31/2022
395962 0001 11/01/2022 12/31/2022
395963 0001 01/01/2022 05/31/2022
395963 0002 06/01/2022 12/31/2022

Employee_ID 395961 和 395962 应该返回查询,因为两者都有日期范围差距。 395961 没有从 04/01/2022 到 05/31/2022 的日期范围。 395962 没有从 05/01/2022 到 05/31/2022 的日期范围。 395963 没有日期范围差距。

我想返回员工有日期范围的月份,并按月分组,因为我们可以获得重复的回报。例如,Employee_ID 395961 将返回一月、二月、三月、一月、六月、七月、八月、九月、十月、十一月、十二月,当我们对月份进行分组时,它会删除重复的一月。然后我们检查缺少哪些月份,如果有任何返回,我们应该考虑返回这个 Employee_ID 作为结果。

我真的没有想出如何获得正确的结果,但我已经做了一些研究以找到以下可能有帮助的方法。我不想使用变量,因为我希望将此查询应用于 1000 条记录。

SELECT  DATENAME(MONTH, DATEADD(MONTH, x.number, @Start_Date)) AS MonthName
FROM    master.dbo.spt_values x
WHERE   x.type = 'P'        
AND     x.number <= DATEDIFF(MONTH, @Start_Date, @End_Date)

【问题讨论】:

  • 您的问题被标记为 mysql,但表引用 master.dbo.spt_values 让我认为您正在使用 Microsoft SQL Server(因为 MySQL 不支持此类目录限定标识符)。能否请您查询SELECT @@version;并确认您使用的是哪个数据库软件?
  • 你的日期真的是字符串吗?
  • @BillKarwin 微软 SQL Server 2017
  • @RiggsFolly - 不,它们是 CCYY-MM-DD 格式的日期。我提供的查询只是一个关于如何从日期范围中获取月份的示例......但实际上这不是我需要的。我什至不知道从哪里开始,所以我只是提供一些作为参考。

标签: sql sql-server date date-range


【解决方案1】:

我认为这应该给你你正在寻找的东西:

WITH cal (date) AS (
    SELECT @Start_Date
    UNION ALL
    SELECT DATEADD(day, 1, date)
    FROM cal
    WHERE date < @End_Date
)
SELECT e.Employee_ID, COUNT(cal.date) AS Days_Not_Hired
FROM cal
CROSS JOIN (SELECT DISTINCT Employee_ID FROM employees) e
LEFT JOIN employees e2
    ON cal.date BETWEEN e2.Start_Date AND e2.End_Date
    AND e.Employee_ID = e2.Employee_ID
WHERE e2.Employee_ID IS NULL
GROUP BY e.Employee_ID
OPTION(MAXRECURSION 365);

db<>fiddle

这是针对 SQL Server 的。它可能需要针对其他方言进行调整。

【讨论】:

  • 使用变量 Start_Date 和 End_Date。不适用于我的场景@nnichols
  • 如果不指定日期范围,您希望如何进行?您是否希望为每位员工从他们的第一个 Start_Date 到他们最后一个 End_Date 做这件事?
  • 我不懂你在说什么。你检查过db<>fiddle了吗?
  • 我宣布了 2022-01-01 和 2022-12-31 的 Start_Date 和 End_Date,并接收了 1 名员工,而它应该返回 2 名员工。
  • 这很奇怪!这些是我用你问题中的虚拟数据设置的小提琴中使用的日期,它返回 (395961, 61) 和 (395962, 31)。
猜你喜欢
  • 2013-11-01
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
相关资源
最近更新 更多