项目中遇到一个需求,要求查出菜单节点的所有节点,在网上查了一下,大多数的方法用到了存储过程,由于线上环境不能随便添加存储过程。
因此在这里采用类似递归的方法对组织下的所有子节点进行查询。
创建组织表:
CREATE TABLE groups (
`group_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '组织ID',
`parent_id` int(11) DEFAULT NULL COMMENT '父节点ID',
`group_name` varchar(128) DEFAULT NULL COMMENT '组织名称',
PRIMARY KEY (`group_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
写入数据:
INSERT INTO groups VALUES (0, null, '系统管理组织');
INSERT INTO groups VALUES (1, 0, '中国电信股份有限公司');
INSERT INTO groups VALUES (2, 1, '万州分公司');
INSERT INTO groups VALUES (3, 1, '涪陵分公司');
INSERT INTO groups VALUES (4, 2, '龙都支局');
INSERT INTO groups VALUES (5, 2, '新田支局');
INSERT INTO groups VALUES (6, 3, '马武支局');
INSERT INTO groups VALUES (7, 3, '南沱支局');
INSERT INTO groups VALUES (8, 4, '党群工作部');
INSERT INTO groups VALUES (9, 5, '客户服务部');
INSERT INTO groups VALUES (10, 6, '采购和供应链管理事业部');
INSERT INTO groups VALUES (11, 7, '网络和信息安全管理部');
树状结构:
- 系统管理组织
- 中国电信股份有限公司
- 万州分公司
- 龙都支局
- 党群工作部
- 新田支局
- 客户服务部
- 涪陵分公司
- 马武支局
- 采购和供应链管理事业部
- 南沱支局
- 网络和信息安全管理部
select
group_id,group_name
from
(
select
t1.group_id,
t1.parent_id,
t1.group_name,
t2.pids,
if(find_in_set(parent_id, @pids) > 0,@pids := concat(@pids, ',', group_id),0) as ischild
from
(select group_id,parent_id,group_name from `groups` ) t1,
(select @pids := #{groupId} as pids) t2) t3
where
ischild != 0;
比如,要查询的万州分公司下所有子节点,只需将#{groupId}变更为万州分公司的组织ID即可:
group_id|group_name|
--------+----------+
4|龙都支局 |
5|新田支局 |
8|党群工作部 |
9|客户服务部 |
group_id|parent_id|group_name |
--------+---------+-----------+
0| |系统管理组织 |
1| 0|中国电信股份有限公司 |
2| 1|万州分公司 |
3| 1|涪陵分公司 |
4| 2|龙都支局 |
5| 2|新田支局 |
6| 3|马武支局 |
7| 3|南沱支局 |
8| 4|党群工作部 |
9| 5|客户服务部 |
10| 6|采购和供应链管理事业部|
11| 7|网络和信息安全管理部 |
pids|
----+
2|
group_id|parent_id|group_name |pids|ischild |
--------+---------+-----------+----+---------+
0| |系统管理组织 | 2|0 |
1| 0|中国电信股份有限公司 | 2|0 |
2| 1|万州分公司 | 2|0 |
3| 1|涪陵分公司 | 2|0 |
4| 2|龙都支局 | 2|2,4 |
5| 2|新田支局 | 2|2,4,5 |
6| 3|马武支局 | 2|0 |
7| 3|南沱支局 | 2|0 |
8| 4|党群工作部 | 2|2,4,5,8 |
9| 5|客户服务部 | 2|2,4,5,8,9|
10| 6|采购和供应链管理事业部| 2|0 |
11| 7|网络和信息安全管理部 | 2|0 |
group_id|group_name|
--------+----------+
4|龙都支局 |
5|新田支局 |
8|党群工作部 |
9|客户服务部 |
引入了通用表表达式(CTE),可以使用CTE来进行递归查询
WITH RECURSIVE subordinates AS (
SELECT group_id, group_name, parent_id
FROM groups
WHERE parent_id = 2 -- 指定父节点ID
UNION ALL
SELECT g.group_id, g.group_name, g.parent_id
FROM groups g
INNER JOIN subordinates s ON s.group_id = g.parent_id
)
SELECT * FROM subordinates;
group_id|group_name|parent_id|
--------+----------+---------+
4|龙都支局 | 2|
5|新田支局 | 2|
8|党群工作部 | 4|
9|客户服务部 | 5|
@Test
public void test1() {
List
[{group_id=4, group_name=龙都支局}, {group_id=5, group_name=新田支局}, {group_id=8, group_name=党群工作部}, {group_id=9, group_name=客户服务部}]
=====================
[{group_id=6, group_name=马武支局}, {group_id=7, group_name=南沱支局}, {group_id=10, group_name=采购和供应链管理事业部}, {group_id=11, group_name=网络和信息安全管理部}]