当数据库中存储了树型结构的数据,例如城市表时,我们要搜索一个城市的所有父级城市或所有的子级城市,首先想到的就是利用SQL的递归查询,来看下面的MySQL例子(下列例子MySQL只适用于8.0版本及以上):

  1. 下载SQL,执行
    表结构和数据SQL文件下载(该文件中中国城市可能不全,数据仅供测试使用)

  2. 向下查询(不包含自己)
    比如我们要查山东省的下级所有城市,拿到山东省这条数据的id:370000

    with recursive tb (id, name, parentid) as(select id, name, parentid from city where parentid = 370000union allselect c.id, c.name, c.parentidfrom city c join tb t on c.parentid = t.id)select *from tb;

    查询结果如下

  3. 向上查询
    比如我们要查历下区的上级所有城市,拿到历下区这条数据的id:370102

    with recursive tb (id, name, parentid) as(select id, name, parentid from city where id = 370102union allselect c.id, c.name, c.parentidfrom city c join tb t on c.id = t.parentid)select *from tb;

    查询结果如下:

当然,我们有时候要查的是上下级的对应关系。
比如我要查出历下区与所有上级城市的关系:中国-山东省-济南市-历下区
或者要查出一个城市下的所有城市与上级城市的关系,只需对上面的SQL稍加修改就可以了:

  1. 一个城市下的所有城市与上级城市的关系
    第一个select中查询条件为该城市的id,在第二个delect中进行拼接处理,拼接字符自选
    拿山东省为例,山东省的id为370000

    with recursive tb (id, name, parentid) as( select id, name, parentidfrom citywhere id = 370000union allselect c.id, concat(t.name, '-', c.name) as name, c.parentid from city cjoin tb ton c.parentid = t.id)select id, name from tb;

    查询结果如下:

  2. 某一城市的父级城市关系
    还是拿历下区举例,拿到id370102

    with recursive tb (id, name, parentid) as(select id, name, parentid from city where id = 370102union allselect c.id, concat(c.name, '-', t.name) as name, c.parentidfrom city c join tb t on c.id = t.parentid)select name from tb where parentid = 0;

    查询结果如下:

其他数据库如DB2等也可以按照同样的思路进行查询,不过需要注意的是其他数据库的SQL语句在with递归的使用和拼接函数concat的使用上可能有不同,进行替换就好