SQL查询需求:查找分区内Start/Stop行配对异常问题
问题描述
现有一张工单操作记录表,需以Work Order、Employee、FunctionGroup作为分区依据,排查每个分区内首次出现的配对异常行。正常规则为:
- 分区内数据必须以
Start开头 - 操作需遵循
Start在前、Stop在后的顺序,可包含多组Start/Stop配对
测试数据
| Work Order | Employee | FunctionGroup | FunctionType | Timestamp |
|---|---|---|---|---|
| WO1 | Emp1 | Group1 | Start | 7/27/23 09:00 |
| WO1 | Emp1 | Group1 | Stop | 7/27/23 10:00 |
| WO1 | Emp1 | Group1 | Start | 7/27/23 11:00 |
| WO1 | Emp1 | Group1 | Stop | 7/27/23 12:00 |
| WO2 | Emp2 | Group2 | Start | 7/27/23 13:00 |
| WO2 | Emp2 | Group2 | Stop | 7/27/23 14:00 |
| WO2 | Emp2 | Group2 | Start | 7/27/23 15:00 |
| WO2 | Emp2 | Group2 | Stop | 7/27/23 16:00 |
| WO3 | Emp3 | Group3 | Start | 7/27/23 17:00(异常:下一行同为Start,需返回此行) |
| WO3 | Emp3 | Group3 | Start | 7/27/23 18:00 |
| WO3 | Emp3 | Group3 | Start | 7/27/23 19:00 |
| WO3 | Emp3 | Group3 | Stop | 7/27/23 20:00 |
| WO4 | Emp4 | Group4 | Stop | 7/27/23 17:00(异常:分区数据以Stop开头,需返回此行) |
| WO4 | Emp4 | Group4 | Start | 7/27/23 18:00 |
| WO4 | Emp4 | Group4 | Start | 7/27/23 19:00 |
| WO4 | Emp4 | Group4 | Stop | 7/27/23 20:00 |
需排查的异常类型
- 分区首行操作是
Stop(违反起始规则) - 连续出现
Start操作(违反顺序规则,上一行是Start时当前行不能再为Start)
SQL查询方案
使用窗口函数LAG()获取分区内上一行的操作类型,结合行号判断首行,筛选异常行后取每个分区的第一个异常:
WITH ranked_data AS ( SELECT *, -- 给分区内的行按时间戳排序编号 ROW_NUMBER() OVER (PARTITION BY `Work Order`, Employee, FunctionGroup ORDER BY Timestamp) AS row_num, -- 获取上一行的FunctionType LAG(FunctionType) OVER (PARTITION BY `Work Order`, Employee, FunctionGroup ORDER BY Timestamp) AS prev_function_type FROM your_table_name -- 过滤原表中的空行 WHERE `Work Order` IS NOT NULL ), exceptions AS ( SELECT *, -- 标记异常原因 CASE WHEN row_num = 1 AND FunctionType = 'Stop' THEN '分区首行为Stop,违反起始规则' WHEN prev_function_type = 'Start' AND FunctionType = 'Start' THEN '连续出现Start,违反顺序规则' END AS exception_reason FROM ranked_data WHERE -- 筛选符合条件的异常行 (row_num = 1 AND FunctionType = 'Stop') OR (prev_function_type = 'Start' AND FunctionType = 'Start') ), first_exceptions AS ( SELECT *, -- 给每个分区的异常行排序,取第一个 ROW_NUMBER() OVER (PARTITION BY `Work Order`, Employee, FunctionGroup ORDER BY Timestamp) AS exception_row_num FROM exceptions ) SELECT `Work Order`, Employee, FunctionGroup, FunctionType, Timestamp, exception_reason FROM first_exceptions WHERE exception_row_num = 1;
说明
- 替换
your_table_name为实际表名 - 适用于支持窗口函数的数据库(如MySQL 8.0+、PostgreSQL、SQL Server等)
- 结果返回每个分区内首次出现的异常行,并标注异常原因
内容的提问来源于stack exchange,提问作者TheMortiestMorty
相关产品推荐
相关产品推荐

