需求: 查出当前用户下面所有的子用户信息. ( 传递父类id )
分析:
方法一: 使用Java程序进行遍历查询. ( 一条一条查询, 执行效率低 )
方法二: sql递归查询. ( 单句查询, 效率比遍历查询高! )
1.库表结构如下: ( 自关联的 - 无限级用户表 )
2.sql语句实现需求:
2.1 查所有的叶子节点. ( 不含自己 )
SELECT u2.id, u2.name
FROM(
SELECT
@ids AS p_ids,
(SELECT @ids := GROUP_CONCAT(id) FROM test_user WHERE FIND_IN_SET(parentId, @ids)) AS c_ids,
@l := @l+1 AS LEVEL
FROM test_user, (SELECT @ids := '101', @l := 0 ) b #此处为需要传递的父类id.
WHERE @ids IS NOT NULL
) u1
JOIN test_user u2
ON FIND_IN_SET(u2.id, u1.p_ids) AND u2.id != '101' #需要包含自己, 则删掉 !=
2.2 查所有的父节点. ( 含自己 )
SELECT u2.id, u2.name
FROM(
SELECT
@id c_ids,
(SELECT @id:=GROUP_CONCAT(parentId) FROM test_user WHERE FIND_IN_SET(id,@id)) p_ids,
@l := @l+1 AS LEVEL
FROM test_user,(SELECT @id:='105', @l := 0) b
WHERE @id IS NOT NULL
) u1
JOIN test_user u2 ON u1.c_ids = u2.id
3.执行过程剖析. ( 中间部分 )
3.1 ( select @ids := ‘101’, @l := 0 )
作用: 初始化一个临时表. ( 存放当前父类id )
- @变量名 : 定义一个用户变量.
- : = 对该用户变量进行赋值.
用户变量赋值有两种方式: 一种是直接用"=“号,另一种是用”:=“号。
其区别在于:
使用set命令对用户变量进行赋值时,两种方式都可以使用;
用select语句时,只能用”:=“方式,因为select语句中,”="号被看作是比较操作符。
3.2 WHERE @ids IS NOT NULL
查询条件, 也是终止条件. ( 若为空(没有子节点了), 即终止! )
3.3 GROUP_CONCAT() 函数
含义:
用于将多个字符串拼接成1个字符串! ( 即行转列. )
完整的语法如下:
group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔符'])
使用:
3.4 FIND_IN_SET(str, strList)
含义:
查询字段(strList)中包含的结果,返回结果null或记录。
- str : 要查询的字符串.
- strList : 字段名,参数以“,”分隔,如(1,2,6,8)
使用: