• mysql笔记(一):递归分类层次查询


    1. 问题描述:

    工作中遇到一个需求,对于一个典型的递归层次分类结构表(组织机构表),要求根据某个节点值找到节点及其所有父级节点。

    (1)示例表结构:

    mysql> desc class;
    +-------------+-------------+------+-----+---------+-------+
    | Field       | Type        | Null | Key | Default | Extra |
    +-------------+-------------+------+-----+---------+-------+
    | org_code    | varchar(20) | NO   |     | NULL    |       |
    | parent_code | varchar(20) | YES  |     | NULL    |       |
    +-------------+-------------+------+-----+---------+-------+
    2 rows in set (0.00 sec)

    (2)示例表数据:

    mysql> select * from class;
    +--------------+-------------+
    | org_code     | parent_code |
    +--------------+-------------+
    | 0001         | NULL        |
    | 00010001     | 0001        |
    | 00010002     | 0001        |
    | 000100010001 | 00010001    |
    | 00010003     | 0001        |
    | 000100010002 | 0001        |
    +--------------+-------------+
    6 rows in set (0.00 sec)

    2. 问题分析

        不想专门加一个函数来做这件事,就想着用sql语句自身的能力来解决类似递归的查询。记得在《mysql技术内幕:sql编程》中解决间断区间问题的一个解决思路:通过自定义变量来记录上一行的值,那我是不是可以自定义变量记录上一个匹配行中父节点的值,进而找到所有匹配行呢?

        貌似可以,但是这两个问题还是有本质不同的,关键区别是前者是一个有序数列,而我这里的数据是无序的字符串编码,所以我需要把它排个序,目的是让所有匹配行的父节点相关的行在其后面出现,这样我每次记录的新的父节点值就都能在接下来的行中找到啦,幸亏我这里的编码是有层次嵌套规则的,所以按照字符串降序就可以了。

    (1)排序

    mysql> select * from class order by org_code desc;
    +--------------+-------------+
    | org_code     | parent_code |
    +--------------+-------------+
    | 00010003     | 0001        |
    | 00010002     | 0001        |
    | 000100010002 | 0001        |
    | 000100010001 | 00010001    |
    | 00010001     | 0001        |
    | 0001         | NULL        |
    +--------------+-------------+
    6 rows in set (0.03 sec)

    (2)逐行过滤记录,更新匹配值为匹配行的父节点

    mysql> select (case when org_code=@r then org_code else null end) as code,
        ->        (case when org_code=@r then @r:=parent_code else null end) as parent
        ->     from (select org_code,parent_code from class order by org_code DESC) as c,(select @r:='000100010001') as t;
    +--------------+----------+
    | code         | parent   |
    +--------------+----------+
    | NULL         | NULL     |
    | NULL         | NULL     |
    | NULL         | NULL     |
    | 000100010001 | 00010001 |
    | 00010001     | 0001     |
    | 0001         | NULL     |
    +--------------+----------+
    6 rows in set (0.03 sec)

    (3)筛选匹配行

    mysql> select code,parent from 
        ->     (select (case when org_code=@r then org_code else null end) as code,
        ->             (case when org_code=@r then @r:=parent_code else null end) as parent
        ->     from (select org_code,parent_code from class order by org_code DESC) as c,(select @r:='000100010001') as t) as tmp 
        -> where code is not null;
    +--------------+----------+
    | code         | parent   |
    +--------------+----------+
    | 000100010001 | 00010001 |
    | 00010001     | 0001     |
    | 0001         | NULL     |
    +--------------+----------+
    3 rows in set (0.00 sec)

    (4)这里我要拿到一个in查询的匹配参数,所以使用group_concat来拼接查询结果,使用的时候再在两端拼上“(‘”和"')"就可以啦

    mysql> select group_concat(code separator "','") as codes from 
        ->     (select (case when org_code=@r then org_code else null end) as code,
        ->             (case when org_code=@r then @r:=parent_code else null end) as parent
        ->     from (select org_code,parent_code from class order by org_code DESC) as c,(select @r:='000100010001') as t) as tmp 
        -> where code is not null;
    +--------------------------------+
    | codes                          |
    +--------------------------------+
    | 000100010001','00010001','0001 |
    +--------------------------------+
    1 row in set (0.00 sec)
  • 相关阅读:
    网络字体图标制作说明
    一些Office365官方的文章连接
    使用Microsoft Graph API整合Office 365
    如何获取Azure 租户ID
    如何在Azure的管理门户中注册应用程序并且分配Graph API权限
    网页简单整合Skype
    如何在windows10中保持Hyper-V与VMWare同时存在
    苹果企业开发者账号申请步骤
    git 取消 文件夹 版本控制
    在 sql server 中,查询 数据库及数据库中各表的大小
  • 原文地址:https://www.cnblogs.com/ling-diary/p/9360606.html
Copyright © 2020-2023  润新知