基于userdays表,查询各用户节假日对应的下一工作日SQL语句
计算每个用户节假日记录的下一工作日
现有表userdays,结构及数据如下:
| Userid | holidaydate |
|---|---|
| 1 | 2023-01-17 |
| 1 | 2023-03-21 |
| 1 | 2023-03-22 |
| 1 | 2023-03-23 |
| 1 | 2023-05-12 |
| 2 | 2023-09-15 |
| 3 | 2023-06-09 |
| 3 | 2023-06-28 |
需求是为每个用户的每条节假日记录计算对应的下一工作日:若当前日期的次日及后续连续日期均为该用户的节假日,则跳过这些日期,返回第一个非节假日日期(比如2023-03-21的下一工作日为2023-03-24,因22、23号都是该用户的节假日)。
解决方案(以MySQL为例)
WITH grouped_holidays AS ( SELECT Userid, holidaydate, SUM(CASE WHEN DATEDIFF(holidaydate, LAG(holidaydate) OVER (PARTITION BY Userid ORDER BY holidaydate)) = 1 THEN 0 ELSE 1 END) OVER (PARTITION BY Userid ORDER BY holidaydate) AS group_id FROM userdays ), group_max_dates AS ( SELECT Userid, group_id, MAX(holidaydate) AS max_holiday FROM grouped_holidays GROUP BY Userid, group_id ) SELECT gh.Userid, DATE_ADD(gmd.max_holiday, INTERVAL 1 DAY) AS nextworkdate FROM grouped_holidays gh JOIN group_max_dates gmd ON gh.Userid = gmd.Userid AND gh.group_id = gmd.group_id ORDER BY gh.Userid, gh.holidaydate;
思路说明
- 分组连续节假日:通过
LAG窗口函数获取每个用户上一条记录的节假日日期,计算当前日期与上一条的天数差。若差为1则属于同一连续组,否则标记新组,用累加的group_id区分不同连续节假日段。 - 获取每组最后一天:按用户和分组ID聚合,得到每组连续节假日的最后一个日期。
- 计算下一工作日:将每组的最后一天加1天,即为该组所有节假日记录对应的下一工作日。
适配其他数据库
- PostgreSQL:将
DATE_ADD(gmd.max_holiday, INTERVAL 1 DAY)替换为gmd.max_holiday + INTERVAL '1 day' - SQL Server:替换为
DATEADD(day, 1, gmd.max_holiday)
执行后将得到符合要求的输出:
| Userid | nextworkdate |
|---|---|
| 1 | 2023-01-18 |
| 1 | 2023-03-24 |
| 1 | 2023-03-24 |
| 1 | 2023-03-24 |
| 1 | 2023-05-13 |
| 2 | 2023-09-16 |
| 3 | 2023-06-10 |
| 3 | 2023-06-29 |
内容的提问来源于stack exchange,提问作者Cassius Clay
相关产品推荐
相关产品推荐

