MYSQL中如何根据父类递归查询出所有的子类 ? ( 自关联 - 无限级关系表 )
需求:查出当前分类下面所有的子分类信息。(传递父类id)
分析:
方法一:使用PHP程序进行遍历查询。(一条一条查询,执行效率低)
方法二:sql递归查询。(单句查询,效率比遍历查询高!)
1.库表结构如下:(自关联的 - 无限级分类表)
2.SQL语句实现需求:
2.1 查询所有的叶子节点(不包含自己):
SELECT
u2.id,
u2.NAME
FROM
(
SELECT
@ids AS p_ids,
( SELECT @ids := GROUP_CONCAT( id ) FROM table_name WHERE FIND_IN_SET( parent_id, @ids ) ) AS c_ids,
@l := @l + 1 AS LEVEL
FROM
table_name,
( SELECT @ids := "8", @l := 0 ) b #此处为需要传递的父类id
WHERE
@ids IS NOT NULL
) u1
JOIN stpc_wood_class u2 ON FIND_IN_SET( u2.id, u1.p_ids )
AND u2.id != "8" #需要包含自己, 则删掉 !=
2.2 查询所有的父节点(包含自己):
SELECT
u2.id,
u2.NAME
FROM
(
SELECT
@id c_ids,
(
SELECT
@id := GROUP_CONCAT( parent_id )
FROM
table_name
WHERE
FIND_IN_SET( id, @id )) p_ids,
@l := @l + 1 AS LEVEL
FROM
table_name,(
SELECT
@id := '42', #此处为要传递的子类id
@l := 0
) b
WHERE
@id IS NOT NULL
) u1
JOIN table_name u2 ON u1.c_ids = u2.id
3.执行过程剖析(中间部分)
3.1 (SELECT @ids := "34", @l := 0)
- @变量名 : 定义一个用户变量
- :=
- 对该用户变量进行赋值。用户变量赋值有两种方式:一种是直接用“=”号,另一种是用“:=”号。 其区别在于:
- 使用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)
使用: