MySQL如何按父级优先、子级次之的规则对父子结构表进行分组?
实现邻接表的父级优先分组方案
嘿,针对你这个邻接表结构的父子分组需求,我给你两种常用的实现思路,看你具体是要展示分组后的列表还是做聚合统计:
一、按父-子顺序展示分组列表
如果你的需求是把每个父节点(根节点,parent为null)和它的所有子节点放在同一组,并且父节点排在组内最前面,子节点紧随其后,可以用下面的SQL:
SELECT t.id, t.parent, t.attr, -- 确定每个节点所属的根组ID:根节点用自己的ID,子节点用父节点ID COALESCE(t.parent, t.id) AS root_group_id FROM t ORDER BY root_group_id, -- 先按根组ID分组 -- 根节点排在组内最前面,子节点靠后 CASE WHEN t.parent IS NULL THEN 0 ELSE 1 END, t.id; -- 子节点按ID排序
执行结果(对应你的测试数据):
| id | parent | attr | root_group_id |
|---|---|---|---|
| 1 | null | 1 | 1 |
| 2 | 1 | 1 | 1 |
| 3 | 1 | 1 | 1 |
| 4 | null | 0 | 4 |
| 5 | 4 | 1 | 4 |
| 6 | 4 | 1 | 4 |
这个逻辑的核心是用COALESCE(t.parent, t.id)给每个节点标记所属的根组,然后通过排序把同一根组的节点聚在一起,同时保证父节点在组内的优先级。就算你的树有更深的层级(比如子节点还有子节点),这个方法依然有效,所有后代节点都会跟在对应的根节点后面。
二、对父-子组进行聚合统计
如果需要对每个父节点及其子节点做聚合计算(比如统计每组的节点总数、attr总和),可以基于根组ID做分组聚合:
SELECT COALESCE(t.parent, t.id) AS group_id, -- 取出该组根节点的attr值 MAX(CASE WHEN t.parent IS NULL THEN t.attr ELSE NULL END) AS parent_attr, COUNT(*) AS total_nodes, -- 组内总节点数 SUM(t.attr) AS total_attr_sum -- 组内attr总和 FROM t GROUP BY group_id ORDER BY group_id;
执行结果(对应你的测试数据):
| group_id | parent_attr | total_nodes | total_attr_sum |
|---|---|---|---|
| 1 | 1 | 3 | 3 |
| 4 | 0 | 3 | 2 |
这个SQL通过GROUP BY group_id把同一根组的节点聚合在一起,再用聚合函数计算你需要的统计值。
内容的提问来源于stack exchange,提问作者Werner
相关产品推荐
相关产品推荐

