如何按项目和工单获取状态为NULL的最低Op Seq ID?
多条件下使用MIN()函数获取工单中未完成工序的最小序列ID
MIN()函数的用法有不少技巧,但下面这个多条件场景更复杂:每个项目(Project)包含多个工单(Work Order),每个工单又包含多个工序序列ID(Op Seq ID)。
表:WorkOrders
| 项目(Project) | 工单(Work Order) | 工序序列ID(Op Seq ID) | 工序状态码(Op Status Code) | 工序名称(Op Name) |
|---|---|---|---|---|
| A | 100 | 10 | Complete(已完成) | Saw(锯切) |
| A | 100 | 20 | Complete(已完成) | Weld(焊接) |
| A | 100 | 30 | NULL | Paint(喷漆) |
| A | 100 | 40 | NULL | Label(贴标) |
| A | 101 | 10 | Complete(已完成) | Laser(激光切割) |
| A | 101 | 20 | NULL | Drill(钻孔) |
| A | 101 | 30 | NULL | Paint(喷漆) |
| B | 115 | 10 | NULL | Laser(激光切割) |
| B | 115 | 20 | NULL | Drill(钻孔) |
需求
在每个项目(Project)中,返回每个工单(Work Order)里工序状态码(Op Status Code)为NULL的最低工序序列ID(Op Seq ID),预期结果如下:
| 项目(Project) | 工单(Work Order) | 工序序列ID(Op Seq ID) | 工序状态码(Op Status Code) | 工序名称(Op Name) |
|---|---|---|---|---|
| A | 100 | 30 | NULL | Paint(喷漆) |
| A | 101 | 20 | NULL | Drill(钻孔) |
| B | 115 | 10 | NULL | Laser(激光切割) |
问题分析与解决方案
你尝试的查询语句存在逻辑问题:既没有过滤状态为NULL的记录,也没有按工单分组,子查询仅关联了项目字段,无法定位到每个工单的最小未完成工序ID。以下是两种可行的解决方法:
方法1:窗口函数ROW_NUMBER()实现
这种方法简洁直观,先过滤出未完成的工序记录,再按项目+工单分组排序,取每组第一条记录:
SELECT [项目(Project)], [工单(Work Order)], [工序序列ID(Op Seq ID)], [工序状态码(Op Status Code)], [工序名称(Op Name)] FROM ( SELECT *, -- 按项目和工单分组,每组内按工序序列ID升序排号 ROW_NUMBER() OVER (PARTITION BY [项目(Project)], [工单(Work Order)] ORDER BY [工序序列ID(Op Seq ID)] ASC) AS rn FROM dbo.WorkOrders WHERE [工序状态码(Op Status Code)] IS NULL ) t WHERE rn = 1 -- 取每组的第一条(即最小序列ID的记录)
方法2:子查询分组+关联原表
先统计每个项目+工单下未完成工序的最小序列ID,再关联原表获取完整记录:
SELECT w.[项目(Project)], w.[工单(Work Order)], w.[工序序列ID(Op Seq ID)], w.[工序状态码(Op Status Code)], w.[工序名称(Op Name)] FROM dbo.WorkOrders w INNER JOIN ( -- 分组获取每个项目+工单的最小未完成工序序列ID SELECT [项目(Project)], [工单(Work Order)], MIN([工序序列ID(Op Seq ID)]) AS MinOpSeqID FROM dbo.WorkOrders WHERE [工序状态码(Op Status Code)] IS NULL GROUP BY [项目(Project)], [工单(Work Order)] ) t ON w.[项目(Project)] = t.[项目(Project)] AND w.[工单(Work Order)] = t.[工单(Work Order)] AND w.[工序序列ID(Op Seq ID)] = t.MinOpSeqID
原查询问题说明
你的原查询仅通过项目字段关联子查询,没有过滤状态为NULL的记录,也未按工单分组,导致无法准确获取每个工单对应的最小未完成工序ID:
-- 原查询(存在逻辑问题) SELECT [WO Project ID], [Op Seq ID] FROM dbo.WorkOrders T1 WHERE [WO Project ID] = (SELECT MIN([Op Seq ID]) FROM dbo.WorkOrders T2 WHERE T1.[WO Project ID] = T2.[WO Project ID])
内容的提问来源于stack exchange,提问作者Sudenga-Steve
相关产品推荐
相关产品推荐

