• MYSQL8.0 WITH RECURSIVE递归查询


    MYSQL 8.0 版本以上 使用 WITH RECURSIVE 实现递归

    注意:写法比较简单,也比较灵活,但是只适用于MySQL8.0及以上版本,这种写法其实和  PostgreSQL 的写法是一样的。

    WITH RECURSIVE 语法

    1. WITH recursive 表名 AS (
    2. 初始语句(非递归部分)
    3. UNION ALL
    4. 递归部分语句
    5. )
    6. [ SELECT| INSERT | UPDATE | DELETE]

    with recursive 由两部分组成。第一部分是非递归部分( union all 上方),第二部分是递归部分(union all下方)。递归部分第一次进入的时候使用非递归部分传递过来的参数,也就是第一行的数据值,进而得到第二行数据值,然后根据第二行数据值得到第三行数据值。

    用法示例

    定义下面这样的表,存储每个区域(省、市、区)的 id,名字及上级区域的 pid

    1. create table tb(id varchar(3) , pid varchar(3) , name varchar(10));
    2. insert into tb values('002' , 0 , '浙江省');
    3. insert into tb values('001' , 0 , '广东省');
    4. insert into tb values('003' , '002' , '衢州市');
    5. insert into tb values('004' , '002' , '杭州市') ;
    6. insert into tb values('005' , '002' , '湖州市');
    7. insert into tb values('006' , '002' , '嘉兴市') ;
    8. insert into tb values('007' , '002' , '宁波市');
    9. insert into tb values('008' , '002' , '绍兴市') ;
    10. insert into tb values('009' , '002' , '台州市');
    11. insert into tb values('010' , '002' , '温州市') ;
    12. insert into tb values('011' , '002' , '丽水市');
    13. insert into tb values('012' , '002' , '金华市') ;
    14. insert into tb values('013' , '002' , '舟山市');
    15. insert into tb values('014' , '004' , '上城区') ;
    16. insert into tb values('015' , '004' , '下城区');
    17. insert into tb values('016' , '004' , '拱墅区') ;
    18. insert into tb values('017' , '004' , '余杭区') ;
    19. insert into tb values('018' , '011' , '金东区') ;
    20. insert into tb values('019' , '001' , '广州市') ;
    21. insert into tb values('020' , '001' , '深圳市') ;

    需要查出某个省,如浙江省,管辖的所有市及市辖地区,示例 sql 如下

    1. with RECURSIVE cte as
    2. (
    3. select a.id, a.name from tb a where id = '002'
    4. union all
    5. select k.id, k.name from tb k inner join cte c on c.id = k.pid
    6. )
    7. select id, name from cte;

    执行结果如下

     实际开发中用到的例子

    // 使用的是postgre,遍历设备树获取指定设备树和所有子节点的测点信息

    1. WITH RECURSIVE tree AS (
    2. SELECT * FROM eqp_tree
    3. WHERE del_flag = 0 AND node_code = #{eqpCode}
    4. UNION
    5. SELECT e.* FROM eqp_tree e INNER JOIN tree s ON e.parent_code = s.node_code AND e.del_flag = 0
    6. ) SELECT
    7. k2.id,
    8. k2.eqp_code,
    9. k2.mp_code,
    10. k2.mp_name,
    11. k2.measure_no,
    12. k2.measureParameters,
    13. k3.location_code,
    14. k3.location_name
    15. FROM
    16. tree k1
    17. JOIN (
    18. SELECT
    19. A.id,
    20. A.eqp_code,
    21. A.mp_code,
    22. A.mp_name,
    23. A.measure_no,
    24. A.measure_position,
    25. array_to_string ( array_agg ( B.measure_parameter ), '|' ) AS measureParameters
    26. FROM
    27. measure_point_info A
    28. LEFT JOIN measure_point_samples_set B ON A.mp_code = B.mp_code
    29. AND B.del_flag = 0
    30. WHERE
    31. A.del_flag = 0
    32. GROUP BY
    33. A.id,
    34. A.eqp_code,
    35. A.mp_code,
    36. A.mp_name,
    37. A.measure_no,
    38. A.measure_position
    39. ) k2 ON k2.eqp_code = k1.node_code
    40. LEFT JOIN configure_model_location K3 ON k3.location_code = k2.measure_position
    41. AND k3.del_flag = 0

    上边 SQL 中用到了 postgresql 数据库实现某一列的数据拼接:array_agg() ,摘录如下

    postgre 中没有 group_concat 函数,网上大部分的解决办法,都是自定义一个 group_concat 函数。其实完全没必要,因为 postgre 中自带的 array_agg() 函数完全可以实现该功能。postgre  中的 array_agg(字段) 等价于mysql 中的 group_concat(字段)。如果想将拼接的数据转换成字符串,可以在 array_agg() 的基础上使用 array_to_string() 方法。即 array_to_string(array_agg(字段),','),其中 ',' 可以换成其他任意间隔符。

    参考文章:mysql 递归函数with recursive的用法_cyan_orange的博客-CSDN博客_mysql recursive

  • 相关阅读:
    ModSecurity开源WAF防火墙和控制面板安装教程
    利用 python 脚本 PyRdp 设置 RDS 服务器蜜罐 Honeypot
    聊聊基于Alink库的决策树模型算法实现
    NX二次开发-调内部函数UGS::UICOMP_enum::set_width(int)更改BlockUI的枚举控件宽度
    前端面试知识整理:vue的钩子函数
    Java手写最大流算法应用拓展案例
    day-45 代码随想录算法训练营(19)动态规划 part 07
    DC-1靶机练习【超详细】
    LCR 078. 合并 K 个升序链表
    centOS 7 Install Harbor(私有镜像仓库)V2
  • 原文地址:https://blog.csdn.net/swadian2008/article/details/126732526