RECURSIVE - 递归查询

实际中往往需要涉及到查询一张表中存在上下级关系的数据。

这样的情景有很多,比如岗位配置表,存在多级部门,部门间存在上下级关系;比如业务字典表,存在多级字典,其中也存在上下级关系。

当层级只有一两层的时候,使用关联查询、子查询或者其它任何方式,都能够比较容易完成查询功能。
例如,当存在一个岗位部门表 POST,其中内容结构如下:

POST_CODE POST_NAME POST_PRE_CODE
president 总裁办公室
business 业务部 president
technical 技术部 president
logistics 后勤部 president
humanResource 人力资源部 president
account 财务部 president
security 安保部 president
culture 企业文化部 president

对这样的结构进行查询,并不困难。如下:

SELECT P.POST_CODE,
       CASE
           WHEN P.POST_PRE_CODE IS NULL THEN P.POST_NAME
           ELSE CONCAT_WS(' - ', (SELECT O.POST_NAME FROM POST O WHERE O.POST_CODE = P.POST_PRE_CODE),
                       P.POST_NAME) END AS POST_NAME
FROM POST P ORDER BY POST_PRE_CODE;

得到的结果:

POST_CODE POST_NAME
president 总裁办公室
business 总裁办公室 - 业务部
technical 总裁办公室 - 技术部
logistics 总裁办公室 - 后勤部
humanResource 总裁办公室 - 人力资源部
account 总裁办公室 - 财务部
security 总裁办公室 - 安保部
culture 总裁办公室 - 企业文化部

但当层级越来越多之后,查询会变得麻烦起来。

例如,当“技术部”存在下属岗位如“研发组”、“美工组”、“测试组”、“运维组”……再当“研发组”又存在下属岗位“软件开发”、“硬件开发”、“大数据开发”……
可想而知,通过上述的查询SQL已经无法轻易完成这样的查询需求。

在这种情况下,使用 RECURSIVE ,进行递归查询是非常适合的。
再举个例子,存在地区区域表 AREA ,最高层级是省,最低层级到某个县/区的某个地点,至少存在四级结构。

此时想要获取某指定省份,如“湖南省”,在表中全部下属的地市、区县及地点,并让每个地点都附带上它所有的上级结构,该如何通过SQL完成?
使用 RECURSIVE 进行递归查询,会让事情变得简单。如下:

WITH RECURSIVE city AS
(
    SELECT AREA_CODE,
           AREA_NAME
    FROM AREAS
    WHERE AREA_CODE = 'hunan'
    UNION ALL
    SELECT org.AREA_CODE,
           CONCAT_WS(' - ', city.AREA_NAME, org.AREA_NAME) AREA_NAME
    FROM city
             JOIN AREAS org ON org.AREA_PID = city.AREA_CODE
)
SELECT AREA_CODE,
       AREA_NAME
FROM city;

最终,我们可以得到下面的结构

POST_CODE POST_NAME
hunan 湖南省
changsha 湖南省 - 长沙市
yueyang 湖南省 - 岳阳市
hengyang 湖南省 - 衡阳市
xiangtan 湖南省 - 湘潭市
furongqu 湖南省 - 长沙市 - 芙蓉区
tianxinqu 湖南省 - 长沙市 - 天心区
yueluqu 湖南省 - 长沙市 - 岳麓区
kaifuqu 湖南省 - 长沙市 - 开福区
yuhuaqu 湖南省 - 长沙市 - 雨花区
wangchengqu 湖南省 - 长沙市 - 望城区
liuyangshi 湖南省 - 长沙市 - 浏阳市
ningxiangshi 湖南省 - 长沙市 - 宁乡市
changshaxian 湖南省 - 长沙市 - 长沙县
junshanqu 湖南省 - 岳阳市 - 君山区
xiangyuxian 湖南省 - 长沙市 - 芙蓉区 - 湘域熙岸小区
chengshihuayuan 湖南省 - 长沙市 - 岳麓区 - 万科城市花园
fangjushoufu 湖南省 - 岳阳市 - 君山区 - 房聚首府小区
junshanyihao 湖南省 - 岳阳市 - 君山区 - 君山壹号

成功得到满足需求的查询结果。
WITH语句本身能够将复杂语句拆分为多个简单语句,在进行复杂的查询时尤其适用。
而 RECURSIVE 关键字则是起到了引入自身的作用,从而实现了递归查询。

不过需要注意的是,RECURSIVE 仅在MySQL8.0以上的版本才能使用哦

你可能感兴趣的:(Tips,database,mysql)