sql入门之递归查询

373 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

在领导给定支持后,我开始学习java后端,刚开始入门要学的比较多,首先是知道java基本语法,数据库sql语法,maven+springboot框架。最近在学习sql时,发现一个比较好用的函数SYS_CONNECT_BY_PATH。

描述

给定一张department表,已知员工A所在部门id为100001,要求查询出当前部门100001所在所有上级部门,并用“/”拼接所有关联部门名称。

表定义department(部门):

列名类型注释
idvarchar主键
namevarchar部门名称
parentidvarchar上级id

SYS_CONNECT_BY_PATH函数,拼接所有路径名称,语法如下:

SYS_CONNECT_BY_PATH(拼接的列名, 定义拼接的字符)
start with 初始条件
connect by prior 循环体条件(注意priod关键字后面的字段取的是上一个循环体中的值)

所以完整的sql写法:

select SYS_CONNECT_BY_PATH(d.name, '/') as full_path from department d
start with d.id = 100001
connect by prior d.parentid = d.id

关键字prior

  1. prior的英文解释是: 先前的,事先的;<正式>优先的,更重要的;所以在sql中表示上一条循环体中的参数。
  2. prior d.parentid表示根据父级id去查询部门,从下往上查询,相反如果需要从上往下查询就调换一下parenid跟id的顺序。注意prior的顺序可以调换,d.id = prior d.parentid也是可以的。

表department样例:

idnameparentid
1研发部4
2研发一部1
3研发二部1
4总部null
100001研发团队12

路径拼接查询获得到的结果:

full_path
/研发团队1/研发一部/研发部/总部
/研发团队1/研发一部/研发部
/研发团队1/研发一部

可以结合max函数,取最长的路径:

select MAX(SYS_CONNECT_BY_PATH(d.name, '/')) as full_path from department d
start with d.id = 100001
connect by prior d.parentid = d.id

或者取parentid is null条件下的路径。

select SYS_CONNECT_BY_PATH(d.name, '/') as full_path from department d
where d.parentid is null
start with d.id = 100001
connect by prior d.parentid = d.id

注意

  1. 如果用reverse函数反转SYS_CONNECT_BY_PATH拼接的字符串,会出现乱码。
  2. 可以用substr函数去掉前面多余的“/”
  3. SYS_CONNECT_BY_PATH的第一个参数里面的分隔符不能和第二个参数一样,例如SYS_CONNECT_BY_PATH(d.name || '/' || d.parentid,'/')。否则会报错:SQL 错误 [30004] [99999]: ORA-30004: 使用 SYS_CONNECT_BY_PATH 函数时, 不能将分隔符作为列值的一部分。