开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情
在领导给定支持后,我开始学习java后端,刚开始入门要学的比较多,首先是知道java基本语法,数据库sql语法,maven+springboot框架。最近在学习sql时,发现一个比较好用的函数SYS_CONNECT_BY_PATH。
描述
给定一张department表,已知员工A所在部门id为100001,要求查询出当前部门100001所在所有上级部门,并用“/”拼接所有关联部门名称。
表定义department(部门):
| 列名 | 类型 | 注释 |
|---|---|---|
| id | varchar | 主键 |
| name | varchar | 部门名称 |
| parentid | varchar | 上级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
- prior的英文解释是: 先前的,事先的;<正式>优先的,更重要的;所以在sql中表示上一条循环体中的参数。
- prior d.parentid表示根据父级id去查询部门,从下往上查询,相反如果需要从上往下查询就调换一下parenid跟id的顺序。注意prior的顺序可以调换,d.id = prior d.parentid也是可以的。
表department样例:
| id | name | parentid |
|---|---|---|
| 1 | 研发部 | 4 |
| 2 | 研发一部 | 1 |
| 3 | 研发二部 | 1 |
| 4 | 总部 | null |
| 100001 | 研发团队1 | 2 |
路径拼接查询获得到的结果:
| 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
注意
- 如果用reverse函数反转SYS_CONNECT_BY_PATH拼接的字符串,会出现乱码。
- 可以用substr函数去掉前面多余的“/”
- SYS_CONNECT_BY_PATH的第一个参数里面的分隔符不能和第二个参数一样,例如SYS_CONNECT_BY_PATH(d.name || '/' || d.parentid,'/')。否则会报错:SQL 错误 [30004] [99999]: ORA-30004: 使用 SYS_CONNECT_BY_PATH 函数时, 不能将分隔符作为列值的一部分。