Mysql 查询指定节点的所有子节点

打印 上一主题 下一主题

主题 754|帖子 754|积分 2272

原文链接:https://www.zhoubotong.site/post/92.html
    通常我们直接通过递归查询来达到实现子节点数据获取的需求,这里不谈存储过程的实现,存储过程普通账号有权限限制,通常也不易于开发者维护,
这里介绍下纯mysql递归实现的方式:
测试数据可以通过之前的一篇文章来模拟。在正式介绍实现之前,我们先了解下几个mysql实现涉及的相关知识点:

    Mysql用户变量

    用户变量无需声明,直接赋值就行。用户变量名不区分大小写。名称的最大长度为64个字符。常用的赋值方式有:

    方式一:使用 SET 赋值。
    可以使用形如 set @变量名=变量值 或者 set@变量名:=变量值 的方式赋值。
  1. SET @var_name = expr [, @var_name = expr] ...
  2. SET @var_name := expr [, @var_name := expr] ...
复制代码
   
    方式二:使用 select 赋值。
  1. select @变量名:=变量值
  2. select @变量名:=字段名 from table where ... limit 1;
复制代码
   
    继续举个例子,表记录如下:

   
   
    注意: 通过查询表给变量赋值时,需保证查询结果只有一条记录,如上result2的结果集这种查询了2条。
    另外再介绍本文实现中涉及的另外2个mysql函数,这里就简单介绍下:

   

    if(express1,express2,express3)条件语句:
    if语句类似三目运算符,当exprss1成立时,执行express2,否则执行express3;
   

    FIND_IN_SET(str,strlist),str 要查询的字符串,strlist 字段名 参数以”,”分隔 如 (1,2,3,6),查询字段(strlist)中包含(str)的结果.
   

    concat_ws()函数, 表示concat with separator,即有分隔符的字符串连接:
    select concat_ws(',','11','22',NULL); 返回 11,22。
    下面进入本文正题,查询当前节点下的所有子节点:
  1. select id
  2. from (
  3.         select t1.id,
  4.             if(
  5.                 find_in_set(pid, @pids) > 0,
  6.                 @pids := CONCAT_WS(',',@pids, id),
  7.                 0
  8.             ) as ischild
  9.         from (
  10.                 select id,
  11.                     pid
  12.                 from city t
  13.                 order by id
  14.             ) t1,
  15.             (
  16.                 select @pids := 11
  17.             ) t2
  18.     ) t3
  19. where ischild != 0;
复制代码
   
   
    上面我们查询节点id=11(武汉市)下的所有节点。上面语句看似复杂,其实不难理解,我们来分下该sql是怎么实现结果集的。
我们先从最里面的子查询分析:
我们看到第二个from后面是跟了两张表:t1和t2, t2是一个用户变量,其结果集作为t2,

    ,t1表很好理解就是city的所有记录作为表t1,我们再看t3表是什么?

    上面高亮部分即为t3的结果集,其目的就是将当前要查询的子节点id用逗号连接,
    如果pid值在@pids中,则设置@pids用其用户变量+id逗号连接组成新字段ischild。因为@pids查询到匹配记录就重新赋值了,
所以大家不难理解其满足条件下的子节点。

上面就是关于递归查询的实现。当然还有另外一种查法:
  1. SELECT t1.id
  2. FROM (SELECT id,pid FROM city WHERE pid IS NOT NULL) t1,
  3.      (SELECT @pid := 11) t2
  4. WHERE FIND_IN_SET(pid, @pid) > 0
  5.   AND @pid := concat(@pid, ',', id)
  6. -- union select id from city where id = 11 order by id;
复制代码
   如果想查询结果包含自身ID(如上面的id=11),加上后边的union即可。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表