如何按执行顺序排序ID非连续的工作流阶段记录?
按工作流执行顺序查询树形结构节点的方案
你的需求本质是对树形结构的工作流节点进行深度优先遍历(DFS),通过生成节点的遍历路径来实现排序,不受ID是否连续的影响。以下是针对不同数据库的具体实现:
支持递归CTE的数据库(MySQL 8.0+、PostgreSQL、SQL Server等)
使用递归公共表表达式(CTE)生成每个节点的完整遍历路径,再按路径排序即可得到工作流执行顺序:
WITH RECURSIVE workflow_path AS ( -- 初始化:选取工作流的根节点(parent_id为NULL),记录初始路径 SELECT id, strategy_id, stage, parent_id, CAST(id AS VARCHAR(255)) AS path FROM workflow_table WHERE parent_id IS NULL UNION ALL -- 递归:关联父节点,拼接当前节点ID到路径中 SELECT w.id, w.strategy_id, w.stage, w.parent_id, CONCAT(wp.path, ',', w.id) AS path FROM workflow_table w INNER JOIN workflow_path wp ON w.parent_id = wp.id ) -- 按路径排序,输出工作流执行顺序 SELECT id, strategy_id, stage, parent_id FROM workflow_path ORDER BY path;
原理说明
- 递归CTE先定位根节点,为其生成初始路径(仅自身ID)
- 逐层递归查找子节点,将父节点的路径与当前节点ID拼接,形成从根到当前节点的完整路径
- 最后按路径的字典序排序,就能保证节点按工作流的执行顺序(根→子→孙的层级顺序)返回
针对你的示例数据,生成的路径依次为:74 → 74,99 → 74,99,75 → 74,99,75,76 → 74,99,75,76,91 → 74,99,75,76,91,78,排序后完全匹配你期望的结果。
不支持CTE的老版本MySQL
如果使用MySQL 5.x等不支持递归CTE的版本,可以通过自定义变量模拟路径生成:
SELECT id, strategy_id, stage, parent_id FROM ( SELECT w.*, @path := CASE WHEN w.parent_id IS NULL THEN CAST(w.id AS VARCHAR(255)) ELSE CONCAT( (SELECT path FROM (SELECT @path AS path) p WHERE FIND_IN_SET(w.parent_id, p.path) > 0), ',', w.id ) END AS path FROM workflow_table w CROSS JOIN (SELECT @path := '') init ORDER BY LENGTH(path), path ) t ORDER BY path;
注意:该方法仅适用于单根节点的工作流,且性能略逊于CTE方案,优先推荐使用递归CTE的实现。
内容的提问来源于stack exchange,提问作者Jamie Armstrong
相关产品推荐
相关产品推荐

