如何用MySQL查询获取无中断的最长连续日期序列
找出员工的连续无中断日期序列
嘿,这个需求很常见,咱们来一步步解决它!针对你给出的员工TTE0149的日期数据,我们可以用窗口函数轻松识别出连续的日期段,还能生成你想要的两种展示格式。
方法思路
核心思路是给连续的日期分配同一个分组ID:通过给每个员工的日期按顺序编号,然后用日期减去对应的编号天数,连续的日期会得到相同的分组值(因为连续日期每天+1,编号也+1,相减后结果不变)。
SQL实现(MySQL为例)
1. 识别所有连续日期段
这个查询会列出所有连续的日期组,包括起止日期、连续天数,以及你要的紧凑格式:
WITH date_groups AS ( SELECT emp_code, date, -- 生成分组ID:连续日期会有相同的group_id DATE_SUB(date, INTERVAL ROW_NUMBER() OVER (PARTITION BY emp_code ORDER BY date) DAY) AS group_id FROM your_table WHERE emp_code = 'TTE0149' -- 只查询目标员工,去掉则处理所有员工 ), consecutive_segments AS ( SELECT emp_code, MIN(date) AS 连续起始日期, MAX(date) AS 连续结束日期, COUNT(*) AS 连续天数, -- 生成你要的紧凑格式:TTE0149 5{1,2,3,4,5} CONCAT(emp_code, ' ', COUNT(*), '{', GROUP_CONCAT(DAY(date) ORDER BY date SEPARATOR ','), '}') AS 紧凑格式展示, -- 生成完整的日期列表格式 GROUP_CONCAT(date ORDER BY date SEPARATOR ', ') AS 完整日期列表 FROM date_groups GROUP BY emp_code, group_id ) -- 按连续天数倒序,优先展示最长的连续段 SELECT * FROM consecutive_segments ORDER BY 连续天数 DESC;
2. 仅获取最长的连续日期段
如果你只需要最长的那一段(也就是你例子里的5天序列),只需要在最后加LIMIT 1即可:
WITH date_groups AS ( SELECT emp_code, date, DATE_SUB(date, INTERVAL ROW_NUMBER() OVER (PARTITION BY emp_code ORDER BY date) DAY) AS group_id FROM your_table WHERE emp_code = 'TTE0149' ), consecutive_segments AS ( SELECT emp_code, MIN(date) AS 连续起始日期, MAX(date) AS 连续结束日期, COUNT(*) AS 连续天数, CONCAT(emp_code, ' ', COUNT(*), '{', GROUP_CONCAT(DAY(date) ORDER BY date SEPARATOR ','), '}') AS 紧凑格式展示, GROUP_CONCAT(date ORDER BY date SEPARATOR ', ') AS 完整日期列表 FROM date_groups GROUP BY emp_code, group_id ) SELECT * FROM consecutive_segments ORDER BY 连续天数 DESC LIMIT 1;
结果说明
针对你提供的数据,这个查询会返回:
- 完整日期列表:
TTE0149 2020-01-01, 2020-01-02, 2020-01-03, 2020-01-04, 2020-01-05 - 紧凑格式:
TTE0149 5{1,2,3,4,5}
如果是其他数据库(比如SQL Server、Oracle),函数语法会略有调整,比如SQL Server用DATEADD(day, -ROW_NUMBER()..., date),Oracle用TRUNC(date) - ROW_NUMBER() OVER (...),有需要的话可以随时问我适配方案~
内容的提问来源于stack exchange,提问作者krishna kumar
相关产品推荐
相关产品推荐

