如何用SQL计算员工完成关键任务的连续天数?
计算员工连续完成关键任务的天数解决方案
不用循环,用窗口函数就能高效解决这个问题,核心思路是先给每个员工的连续关键任务段打上分组标记,再在分组内计数。
假设你的临时表名为#EmployeeTasks,字段分别是员工(EmployeeName)、日期(TaskDate)、Task_List、Critical_Task,可以用下面的SQL语句计算Consec_Days_Crit_Task:
SELECT EmployeeName AS 员工, TaskDate AS 日期, Task_List, Critical_Task, CASE WHEN Critical_Task = 1 THEN ROW_NUMBER() OVER ( PARTITION BY EmployeeName, GroupId ORDER BY TaskDate ) ELSE 0 END AS Consec_Days_Crit_Task FROM ( SELECT *, -- 按员工分区,按日期排序,累计统计前面出现的0的数量,以此作为分组标识 SUM(CASE WHEN Critical_Task = 0 THEN 1 ELSE 0 END) OVER ( PARTITION BY EmployeeName ORDER BY TaskDate ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS GroupId FROM #EmployeeTasks ) AS GroupedTasks ORDER BY EmployeeName, TaskDate;
逻辑说明:
- 分组标记(GroupId):按员工分区,按日期顺序遍历记录,每遇到一条
Critical_Task=0的记录,就给后续的记录加一个分组编号。这样连续的Critical_Task=1的记录会被分到同一个GroupId下,一旦出现0,分组就会切换。 - 连续天数计数:在每个员工+GroupId的分区内,对
Critical_Task=1的记录按日期排序生成行号,这行号就是连续完成关键任务的天数;Critical_Task=0的记录直接返回0。
执行结果(和示例匹配):
| 员工 | 日期 | Task_List | Critical_Task | Consec_Days_Crit_Task |
|---|---|---|---|---|
| Tom J | 10/1/22 | Sweep, Lock Door* | 1 | 1 |
| Tom J | 10/2/22 | Sweep, Lock Door* | 1 | 2 |
| Tom J | 10/3/22 | Mop, Dishes | 0 | 0 |
| Tom J | 10/4/22 | Sweep, Lock Door* | 1 | 1 |
| Sue B | 10/1/22 | Mop, Dishes | 0 | 0 |
| Sue B | 10/2/22 | Mop, Dishes | 0 | 0 |
| Sue B | 10/3/22 | Sweep, Lock Door* | 1 | 1 |
| Sue B | 10/4/22 | Mop, Dishes | 0 | 0 |
内容的提问来源于stack exchange,提问作者DougCash
相关产品推荐
相关产品推荐

