功能:
在树形结构的表里,从某些行出发,沿着上级或下级的关系,一层一层地找出相关的记录。
语法:
递归 [方向] 起始 <起始条件式> 选出列 {<计算式> [命名 <新列名>]} [层次 <层次列名>] [主键 <主键字段>] [父列 <父列字段>] [条件 <条件式>]
规则:
这里的"树形结构"是指,表里有两个字段,一个字段能唯一区分每一行(比如员工编号),另一个字段记录"这一行的上级是哪一行"(比如上级编号);这两个字段就把整个表组织成了一棵树,最上面那一行没有上级,是树的根。
本功能相当于SQL里的递归子查询(WITH RECURSIVE),并在此基础上做了归纳和扩展:参数起始相当于SQL里最先查出的那部分行,参数方向、父列、主键决定后面怎么一层层地找下去,参数层次相当于递归的层数。
下面将使用员工表作为焦点表来介绍递归功能,员工表的主键为员工编号,表数据内容如下:
|
员工编号 |
姓名 |
上级编号 |
推荐人编号 |
部门 |
工资 |
|
E01 |
张伟 |
|
|
总经理室 |
30000 |
|
E02 |
李娜 |
E01 |
E01 |
销售部 |
15000 |
|
E03 |
王强 |
E01 |
E02 |
技术部 |
18000 |
|
E04 |
赵敏 |
E02 |
E03 |
销售部 |
9000 |
|
E05 |
刘洋 |
E02 |
E03 |
销售部 |
8000 |
|
E06 |
陈静 |
E03 |
E01 |
技术部 |
12000 |
|
E07 |
杨帆 |
E03 |
E06 |
技术部 |
7000 |
|
E08 |
周涛 |
E04 |
E07 |
销售部 |
5000 |
说明:该表可以看做两个树形结构,按上级编号看,这棵树是:张伟下面有李娜、王强;李娜下面有赵敏、刘洋;王强下面有陈静、杨帆;赵敏下面是周涛。按推荐人编号看,是另一棵树:张伟推荐了李娜、陈静;李娜推荐了王强;王强推荐了赵敏、刘洋;陈静推荐了杨帆;杨帆推荐了周涛。张伟既没有上级、也没有推荐人,所以他是两棵树的根。
参数:方向
查找的方向。
必填,省略参数名。枚举类型,枚举值:
- 向上:从起始行出发找上级,也就是沿着参数父列一直往根的方向找。
- 向下:从起始行出发找下级,也就是沿着参数父列一直往叶子的方向找。
示例:
递归 向上 起始 (姓名="赵敏") 选出列 姓名 父列 上级编号 //从赵敏出发,向上找出她的所有上级,结果如下:
|
姓名 |
|
赵敏 |
|
李娜 |
|
张伟 |
解释:赵敏是起始行(第1层);她的上级是李娜(第2层);李娜的上级是张伟(第3层);张伟没有上级,就不再有下一层了。结果里行的先后顺序,就是一层一层找上来的顺序。
递归 向下 起始 (上级编号 为空) 选出列 姓名 父列 上级编号 //从张伟出发,向下找出他的所有下级,结果如下:
|
姓名 |
|
张伟 |
|
李娜 |
|
王强 |
|
赵敏 |
|
刘洋 |
|
陈静 |
|
杨帆 |
|
周涛 |
解释:张伟是第1层,李娜和王强是第2层,赵敏、刘洋、陈静、杨帆是第3层,周涛是第4层。同一层的记录排在一起,同一层里按焦点表原来的顺序排列。
参数:起始
将满足条件的行作为起点,起点本身是第一层,可一行或多行。
必填,不可省略参数名。
示例:
递归 向下 起始 (姓名="李娜") 选出列 姓名 父列 上级编号 //从李娜开始,向下找出她和她的所有下级,结果如下:
|
姓名 |
|
李娜 |
|
赵敏 |
|
刘洋 |
|
周涛 |
解释:起点是李娜,不是根,所以结果里没有张伟、王强、陈静、杨帆,他们不在李娜下面。
递归 向上 起始 (部门="技术部") 选出列 姓名 父列 上级编号 //技术部有三个人(王强、陈静、杨帆),从他们三个一起出发向上找各自的上级,结果如下:
|
姓名 |
|
王强 |
|
张伟 |
|
陈静 |
|
王强 |
|
张伟 |
|
杨帆 |
|
王强 |
|
张伟 |
解释:条件"部门='技术部'"同时选中3行(王强、陈静、杨帆),这3行都是起点,都是第1层;再往上找一层,他们的上级都是张伟,张伟是第2层。多行起点时,每个起点依次带出自己到根的整条链:王强的上级是张伟;陈静的上级是王强、王强的上级是张伟;杨帆的上级是王强、王强的上级是张伟。本功能不再去掉重复的行,所以王强出现3次(1次起点、2次上级)、张伟出现3次(都是上级)。
参数:选出列 <计算式> [命名 <新列名>]
指定结果里要哪些列。
必填,不可省略参数名,复合参数,由计算式+命名组成,多组表示选出多个列,多组之间用逗号分隔。
示例:
递归 向下 起始 (上级编号 为空) 选出列 姓名, 部门, 工资 父列 上级编号 //从张伟出发向下找出全部记录,结果里要姓名、部门、工资三个列,结果如下:
|
姓名 |
部门 |
工资 |
|
张伟 |
总经理室 |
30000 |
|
李娜 |
销售部 |
15000 |
|
王强 |
技术部 |
18000 |
|
赵敏 |
销售部 |
9000 |
|
刘洋 |
销售部 |
8000 |
|
陈静 |
技术部 |
12000 |
|
杨帆 |
技术部 |
7000 |
|
周涛 |
销售部 |
5000 |
解释:结果里列的先后顺序,就是你写"选出列"的先后顺序。
计算式:
子参数计算式是参数选出列里每一组的计算式。可以直接是列名或表达式。
必填,省略参数名。本参数不支持跨行计算和聚合计算。
示例:
递归 向上 起始 (姓名="赵敏") 选出列 姓名,工资*1.1 父列 上级编号 // 从赵敏出发向上找出她的所有上级,用计算式"工资*1.1"算出调整后工资,结果如下:
|
姓名 |
工资*1.1 |
|
赵敏 |
9900.0 |
|
李娜 |
16500.0 |
|
张伟 |
33000.0 |
命名:
子参数命名是参数选出列里每一组的列名,省略时沿用原列名,计算式非单列时自动用计算式当列名。
可选,不可省略参数名。注意,本参数要和计算式搭配使用。
示例:
递归 向上 起始 (姓名="赵敏") 选出列 姓名 命名 员工 部门 工资*1.1 命名 调整后工资 父列 上级编号 //从赵敏出发向上找出她的所有上级,用计算式"工资*1.1"计算出结果后列命名为【调整后工资】 ,姓名列命名为【员工】,结果如下:
|
员工 |
调整后工资 |
|
赵敏 |
9900.0 |
|
李娜 |
16500.0 |
|
张伟 |
33000.0 |
参数:层次
给结果中增加层次列,列值为层次号,起始行为第1层,每往下一层加1。
可选,不可省略参数名。
示例:
递归 向下 起始 (上级编号 为空) 选出列 姓名 层次 层级 父列 上级编号 //从张伟出发向下找出全部记录,并且要一个层次号列,列名叫"层级",结果如下:
|
姓名 |
层级 |
|
张伟 |
1 |
|
李娜 |
2 |
|
王强 |
2 |
|
赵敏 |
3 |
|
刘洋 |
3 |
|
陈静 |
3 |
|
杨帆 |
3 |
|
周涛 |
4 |
递归 向上 起始 (姓名="赵敏") 选出列 姓名 层次 层级 父列 上级编号 // 从赵敏出发向上找出她的所有上级,并且要一个层次号列,列名叫"层级",结果如下:
|
姓名 |
层级 |
|
赵敏 |
1 |
|
李娜 |
2 |
|
张伟 |
3 |
解释:不管向上还是向下,起始行都是第1层,往上或往下每一层加1。
参数:主键
能唯一区分每一行的字段,用于判断是否已经找过。
可选,不可省略参数名。省略时用表的主键。
注意,本参数只是内部用来认行的,不会出现在结果里,结果里有哪些列由参数选出列决定。
示例:
递归 向下 起始 (上级编号 为空) 选出列 姓名 层次 层级 主键 员工编号 父列 上级编号 // 从张伟出发向下找出全部记录,并且写出主键是员工编号,结果如下:
|
姓名 |
层级 |
|
张伟 |
1 |
|
李娜 |
2 |
|
王强 |
2 |
|
赵敏 |
3 |
|
刘洋 |
3 |
|
陈静 |
3 |
|
杨帆 |
3 |
|
周涛 |
4 |
由于员工表中主键为员工编号,所以上面递归语句中”主键 员工编号”可以省略。
参数:父列
记录"这一行的上级是谁"的字段,不同父列会得到不同的树形结构。
必填,不可省略参数名。
示例:
递归 向上 起始 (姓名="赵敏") 选出列 姓名, 部门 父列 上级编号 // 按上级编号这棵树,从赵敏出发向上找出她的所有上级,结果如下:
|
姓名 |
部门 |
|
赵敏 |
销售部 |
|
李娜 |
销售部 |
|
张伟 |
总经理室 |
递归 向下 起始 (推荐人编号 为空) 选出列 姓名, 部门 父列 推荐人编号 //换成推荐人编号这棵树,从张伟出发向下找出全部记录,结果与上例不同,结果如下:
|
姓名 |
部门 |
|
张伟 |
总经理室 |
|
李娜 |
销售部 |
|
王强 |
技术部 |
|
赵敏 |
销售部 |
|
刘洋 |
销售部 |
|
陈静 |
技术部 |
|
杨帆 |
技术部 |
|
周涛 |
销售部 |
解释:按推荐关系,张伟推荐了李娜、陈静;李娜推荐了王强;王强推荐了赵敏、刘洋;陈静推荐了杨帆;杨帆推荐了周涛。这棵树和按上级编号看的那棵树不一样,所以结果也不一样。
参数:条件
对起始行之外的结果做额外的筛选,只保留满足这个条件的行。起始行不满足条件不会影响继续往下一层找。
可选,不可省略参数名。
示例:
递归 向下 起始 (上级编号 为空) 选出列 姓名, 工资 条件 (工资>=8000) 父列 上级编号 //从张伟出发向下找出全部记录,结果里只要工资不低于8000的,结果如下:
|
姓名 |
工资 |
|
张伟 |
30000 |
|
李娜 |
15000 |
|
王强 |
18000 |
|
赵敏 |
9000 |
|
刘洋 |
8000 |
|
陈静 |
12000 |
递归 向下 起始 (上级编号 为空) 选出列 姓名, 部门 条件 (部门="销售部") 父列 上级编号 //从张伟出发向下找出全部记录,结果里只要销售部的,结果如下:
|
姓名 |
部门 |
|
张伟 |
总经理室 |
|
李娜 |
销售部 |
|
赵敏 |
销售部 |
|
刘洋 |
销售部 |
|
周涛 |
销售部 |
解释:张伟是总经理室,不满足"销售部"这个条件,但他是起始行,所以仍保留在结果里;他的下级李娜、王强照常往下找,所以李娜这一支的记录仍然出现在结果里。这说明参数条件只筛除起始行之外的记录,不影响往下找。