递归查询语法
功能描述
Vastbase G100兼容Oracle递归查询START WITH...CONNECT BY...
语法,并且CONNECT BY
支持多表连接查询。
语法格式
START WITH condition1 CONNECT BY condition
CONNECT BY condition [ START WITH condition1 ]
参数说明
condition1
表示递归的初始条件。若省略该子句,单独使用CONNECT BY子句,则表示以表中的所有行作为初始集合。
condition
任何条件语句。condition的格式必须为:
[PRIOR column1 = column2 | column1 = prior column2] [PRIOR table_name.column_name=table_name.column_name | PRIOR table_name.column_name=table_name.column_name ]
其中PRIOR表示对列指定PRIOR关键字代表以这列为递归键进行递归。当前约束只能对表中的列指定PRIOR,不支持对表达式、类型转换指定PRIOR关键字。
示例
示例1: 单表递归查询。
1、创建测试表并插入数据。
create table employee(
emp_id number(18),
lead_id number(18),
emp_name varchar2(200),
salary number(10,2),
dept_no varchar2(8)
);
insert into employee values('1',0,'king','1000000.00','001');
insert into employee values('2',1,'jack','50500.00','002');
insert into employee values('3',1,'arise','60000.00','003');
insert into employee values('4',2,'scott','30000.00','002');
insert into employee values('5',2,'tiger','25000.00','002');
insert into employee values('6',3,'wudde','23000.00','003');
insert into employee values('7',3,'joker','21000.00','003');
2、查询以emp_id为3开始的节点的所有直属节点。
select emp_id,lead_id,emp_name
from employee
start with lead_id=3
connect by prior emp_id = lead_id;
返回结果为:
emp_id | lead_id | emp_name
--------+---------+----------
6 | 3 | wudde
7 | 3 | joker
(2 rows)
示例2: 多表连接查询。
1、创建测试表并插入数据。
create table t1(id int);
create table t2(id int);
declare
i int:=0;
begin
for i in 1..5 loop
insert into t1 values(i);
insert into t2 values(i+1);
end loop;
commit;
end;
/
2、执行多表连接查询。
select t1.id as id1,t2.id as id2 from t1,t2 where t1.id+1=t2.id start with t1.id=1 connect by prior t2.id=t1.id;
返回结果为:
id1 | id2
-----+-----
1 | 2
2 | 3
3 | 4
4 | 5
5 | 6
(5 rows)
connect_by_isleaf选项
功能描述
递归查询中的一个伪列,用于指示当前行是否为树的叶子节点(即没有子节点的节点),如果是返回1,否则返回0。
语法格式
SELECT ... CONNECT_BY_ISLEAF "IsLeaf",[LEVEL],
from table
start with condition1
connect by condition;
参数说明
LEVEL
一个伪列(可选),代表当前这个节点所在的层级,对于根节点,level返回1。
IsLeaf
表示当前行是否为树的叶子节点(即没有子节点的节点),如果是返回1,否则返回0。
注意事项
当未指定prior时,connect_by_isleaf始终为0。
示例
1、创建测试表并插入数据。
CREATE TABLE EMP(EMPNO NUMBER(4) NOT NULL,ENAME VARCHAR2(10),JOB VARCHAR2(9),MGR NUMBER(4),HIREDATE DATE,SAL NUMBER(7, 2),COMM NUMBER(7, 2),DEPTNO NUMBER(2));
INSERT INTO EMP VALUES (7369, 'SMITH', 'CLERK', 7902,TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP VALUES (7499, 'ALLEN', 'SALESMAN', 7698,TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP VALUES (7521, 'WARD', 'SALESMAN', 7698,TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP VALUES (7566, 'JONES', 'MANAGER', 7839,TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES (7654, 'MARTIN', 'SALESMAN', 7698,TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES (7698, 'BLAKE', 'MANAGER', 7839,TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES (7782, 'CLARK', 'MANAGER', 7839,TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES (7788, 'SCOTT', 'ANALYST', 7566,TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES (7839, 'KING', 'PRESIDENT', NULL,TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES (7844, 'TURNER', 'SALESMAN', 7698,TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30);
INSERT INTO EMP VALUES (7876, 'ADAMS', 'CLERK', 7788,TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES (7900, 'JAMES', 'CLERK', 7698,TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP VALUES (7902, 'FORD', 'ANALYST', 7566,TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES (7934, 'MILLER', 'CLERK', 7782,TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
2、查询当前行是否为叶子节点
SELECT ename, CONNECT_BY_ISLEAF "IsLeaf",LEVEL
FROM emp
WHERE LEVEL <= 3 AND deptno= 10
START WITH empno = 7839
CONNECT BY PRIOR deptno = mgr AND LEVEL <= 4
order by ename,"IsLeaf";
返回结果为:
ename | IsLeaf | level
-------+--------+-------
KING | 1 | 1
(1 row)
connect_by_iscycle选项
功能描述
递归查询中的一个伪列,用于指示当前行是否为循环行,如果是则返回1,否则返回0。
语法格式
SELECT ... CONNECT_BY_ISCYCLE "IsCYCLE",[LEVEL],
from table
start with condition1
connect by condition;
参数说明
LEVEL
一个伪列(可选),代表当前这个节点所在的层级,对于根节点,level返回1。
IsCYCLE
表示当前行是否为循环行,如果是则返回1,否则返回0。
注意事项
当未指定prior时,connect_by_iscycle始终为0。
示例
1、创建测试表cyctest并插入测试数据。
create table cyctest(tn varchar,fatherid number,childid number);
insert into cyctest values('a',null,1);
insert into cyctest values('b',1,2);
insert into cyctest values('c',1,3);
insert into cyctest values('d',2,4);
insert into cyctest values('e',4,1);
insert into cyctest values('f',4,5);
2、使用connec_by_cycle查询循环行。
select tn,fatherid,childid,connect_by_iscycle iscycle ,level from cyctest start with fatherid is null connect by nocycle prior childid=fatherid;
结果返回如下:
tn | fatherid | childid | iscycle | level
----+----------+---------+---------+-------
a | | 1 | 0 | 1
b | 1 | 2 | 0 | 2
d | 2 | 4 | 1 | 3
f | 4 | 5 | 0 | 4
c | 1 | 3 | 0 | 2
(5 rows)
order siblings by选项
功能描述
排序子句,可对结果集进行排序,仅用于层次查询connect by
中,可以让兄弟节点(即同一父级的兄弟)按照指定的列进行排序(升序或者降序)。
语法格式
SELECT ...
FROM table
start with condition1
connect by condition
ORDER SIBLINGS BY expression
参数说明
table
表名。
expression
排序的依据。
注意事项
无。
示例
1、创建测试表并插入数据。
CREATE TABLE family_tree(id int primary key,appellation varchar(30),parent_id int,age int);
insert into family_tree values(1,'爷爷',0,88);
insert into family_tree values(2,'大伯',1,66);
insert into family_tree values(5,'堂兄',2,32);
insert into family_tree values(6,'堂妹',2,24);
insert into family_tree values(3,'爸爸',1,58);
insert into family_tree values(7,'小明',3,26);
insert into family_tree values(4,'小姑',1,52);
insert into family_tree values(8,'表姐',4,28);
insert into family_tree values(9,'表弟',4,20);
2、对同已父级的兄弟进行排序。
SELECT * FROM family_tree
CONNECT BY PRIOR id= parent_id
start with appellation ='爷爷'
order siblings by age asc;
返回结果为:
id | appellation | parent_id | age
----+-------------+-----------+-----
1 | 爷爷 | 0 | 88
4 | 小姑 | 1 | 52
9 | 表弟 | 4 | 20
8 | 表姐 | 4 | 28
3 | 爸爸 | 1 | 58
7 | 小明 | 3 | 26
2 | 大伯 | 1 | 66
6 | 堂妹 | 2 | 24
5 | 堂兄 | 2 | 32
(9 rows)
connect_by_root选项
功能描述
一个一元运算符,可用于限定列,仅在递归查询中有效,可以根据当前行返回被视为根节点的行的列值,即可以根据当前行得到其根节点的列值。
CONNECT_BY_ROOT运算符可在SELECT列表、WHERE子句、GROUP BY子句、HAVING子句、ORDER BY子句和ORDER SIBLINGS BY子句中使用,只要SELECT命令用于分层查询。不能在分层查询的CONNECT BY子句或START WITH子句中使用。可将CONNECT_BY_ROOT应用于一个涉及列的表达式,但这样做时,该表达式必须用圆括号括起。
语法格式
SELECT CONNECT_BY_ROOT cloumn [, ...] from table start with condition1 connect by condition
参数说明
cloumn
CONNECT_BY_ROOT子句用于显示根节点的列值,col为输出列的名称。
table
表名。
注意事项
无。
示例
本示例测试表使用order siblings by选项示例中所创建的表。
对同已父级的兄弟进行排序。
SELECT connect_by_root parent_id root, connect_by_isleaf isleaf,id,appellation,age FROM family_tree CONNECT BY PRIOR id= parent_id start with appellation ='爷爷' order siblings by age;
返回结果为:
root | isleaf | id | appellation | age ------+--------+----+-------------+----- 0 | 0 | 1 | 爷爷 | 88 0 | 0 | 4 | 小姑 | 52 0 | 1 | 9 | 表弟 | 20 0 | 1 | 8 | 表姐 | 28 0 | 0 | 3 | 爸爸 | 58 0 | 1 | 7 | 小明 | 26 0 | 0 | 2 | 大伯 | 66 0 | 1 | 6 | 堂妹 | 24 0 | 1 | 5 | 堂兄 | 32 (9 rows)