如何通过SQL实现分类按父类分组并字母排序(含多层级方案)
一级子类场景的SQL实现
如果只有一级子类,直接用SQL就能实现你要的排序效果——父类按字母顺序排列,子类紧跟对应父类下方且自身也按字母排序。给你两种实用写法:
第一种通过拼接排序键实现:
SELECT id, parent_id, name, CASE WHEN parent_id IS NULL THEN name ELSE (SELECT name FROM categories WHERE id = c.parent_id) || ' - ' || c.name END AS sort_key FROM categories c ORDER BY sort_key;
第二种更简洁,用COALESCE定义排序依据:
SELECT id, parent_id, name FROM categories c ORDER BY -- 先按父类名称排序,父类的父类名称就是自身name COALESCE((SELECT name FROM categories WHERE id = c.parent_id), name), -- 让父类排在子类前面,给父类设更高优先级 CASE WHEN parent_id IS NULL THEN 0 ELSE 1 END, name;
多层级子类的实现思路
如果要支持多层级嵌套(父→子→孙→...),目前常用两种SQL方案:
递归CTE(推荐现代数据库使用)
MySQL 8.0+、PostgreSQL、SQL Server等现代数据库都支持递归CTE,能遍历整个分类树并生成完整路径,以此作为排序依据:
WITH RECURSIVE category_tree AS ( -- 先获取所有顶级父类 SELECT id, parent_id, name, name AS path, 1 AS level FROM categories WHERE parent_id IS NULL UNION ALL -- 递归遍历子类、孙类,拼接完整路径 SELECT c.id, c.parent_id, c.name, ct.path || ' > ' || c.name AS path, ct.level + 1 AS level FROM categories c JOIN category_tree ct ON c.parent_id = ct.id ) SELECT id, parent_id, name FROM category_tree ORDER BY path;
按生成的path排序后,所有层级的子类都会紧跟对应父类,且每个层级内部保持字母顺序。
预存路径字段(兼容老版本数据库)
如果用的是MySQL 5.x这类不支持递归CTE的数据库,可以给表新增一个path字段,存储类似电子产品/手机/智能手机或001/003/002的结构化路径字符串,新增、修改分类时同步维护这个字段的值。查询时直接按path排序即可:
SELECT id, parent_id, name, path FROM categories ORDER BY path;
这种方式查询效率高,但需要额外维护路径字段,增删改分类时要同步更新所有子节点的路径。
内容的提问来源于stack exchange,提问作者Phaelax
相关产品推荐
相关产品推荐

