add common table expression in MySQL (#314)

This commit is contained in:
Aristoeu
2021-09-02 14:24:01 +08:00
committed by wangzelin.wzl
parent 5f209b30fe
commit 153f16ad8a
33 changed files with 136129 additions and 40650 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
with cte(a,b) as (select 1 from dual) select * from cte;
ERROR 5740 (HY000): number of WITH clause column names does not match number of elements in select list
with cte(a,b) as (with cte2(a,b) as (select 1,1 from dual) select a,b from cte) select * from cte;
ERROR 5742 (HY000): recursive WITH clause must use a UNION ALL operation
with cte(a,a) as (select 1 from dual) select * from cte;
ERROR 5751 (HY000): duplicate name found in column alias list for WITH clause
with cte as (select 1,1 from dual union all select a+1,b+1 from cte where cte.a < 10) select * from cte;
ERROR 1054 (42S22): Unknown column 'cte.a' in 'where clause'
# MySQL不支持search depth关键字
with cte(a,b,c) as
(
select 1,2,3 from dual
union all
select a+1,b+1,c+1 from cte where cte.c < 10
) search depth first by d set pcol select * from cte;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your OceanBase version for the right syntax to use near 'search depth first by d set pcol select * from cte' at line 6
# MySQL不支持cycle关键字
with cte(n, x) as (select /*+ materialize */ 1,2 from dual) cycle n,n set iscyc to 'aaaaay' default 'n' select * from cte;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your OceanBase version for the right syntax to use near 'cycle n,n set iscyc to 'aaaaay' default 'n' select * from cte' at line 1
with cte(a,b,c) as
(
select 1,2,3 from dual
union
select a+1,b+1,c+1 from cte, cte b where cte.c < 10 and b.c = cte.c
) select * from cte;
ERROR 5742 (HY000): recursive WITH clause must use a UNION ALL operation
with cte(a,b,c) as
(
select 1,2,3 from dual
union all
select 1,2,3 from dual
union all
select a+1,b+1,c+1 from cte, cte b where cte.c < 10 and b.c = cte.c
) select * from cte;
ERROR 5762 (HY000): recursive query name referenced more than once in recursive branch of recursive WITH clause element
with t1 as (select c1 from t1) select * from t1;
ERROR 5741 (HY000): recursive WITH clause must have column alias list
## success
with cte1(a,b) as (select 'a','b' from dual), cte2 as (select * from cte1 where b > 'c'), cte3 as (select * from cte2 where a > 1 union select * from cte2 where a > 1) select * from cte3;
Empty set
with cte(a) as (select 1,1 from dual union all select a+1, a+1 from cte where a+1 < 10) select * from cte;
ERROR 5740 (HY000): number of WITH clause column names does not match number of elements in select list
with cte(n) AS (select 1 from dual UNION ALL select n+1 from cte where n < 3 UNION ALL select 2 from dual) select * from cte;
ERROR 5743 (HY000): UNION ALL operation in recursive WITH clause must have only two branches
with cte(n) AS ( select 1 from dual UNION ALL select sum(n+1) from cte) select * from cte;
ERROR 5758 (HY000): unsupported operation in recursive branch of recursive WITH clause
with cte(n) AS ( select 1 from dual UNION ALL select (select 1 from dual) from cte where cte.n < 2) select * from cte;
ERROR 5746 (HY000): cycle detected while executing recursive WITH query
with cte (c1, c2, c3) as ( select * from ( select c1, c2, c3 from t1 union select c1, c2, c3 from t1) where c1 = 1 union all select * from t1 join cte c on t1.c1 = c.c1 where c.c1 < 10 ) select * from cte;
ERROR 1222 (21000): The used SELECT statements have a different number of columns
with cte(n) AS ( select 1 from cte) select * from cte;
ERROR 5742 (HY000): recursive WITH clause must use a UNION ALL operation
with cte(n) AS (select 1 from dual UNION ALL select n+1 from cte where n < 3 order by n ) select * from cte;
ERROR 1054 (42S22): Unknown column 'n' in 'order clause'

View File

@ -0,0 +1,796 @@
WITH RECURSIVE cte (n) AS
(
SELECT 1
UNION ALL
SELECT n + 1 FROM cte WHERE n < 5
)
SELECT * FROM cte;
+------+
| n |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
WITH RECURSIVE cte AS
(
SELECT 1 AS n, CAST('abc' AS CHAR(20)) AS str
UNION ALL
SELECT n + 1, CONCAT(str, str) FROM cte WHERE n < 3
)
SELECT * FROM cte;
+------+--------------+
| n | str |
+------+--------------+
| 1 | abc |
| 2 | abcabc |
| 3 | abcabcabcabc |
+------+--------------+
WITH RECURSIVE cte AS
(
SELECT 1 AS n, 1 AS p, -1 AS q
UNION ALL
SELECT n + 1, q * 2, p * 2 FROM cte WHERE n < 5
)
SELECT * FROM cte;
+------+------+------+
| n | p | q |
+------+------+------+
| 1 | 1 | -1 |
| 2 | -2 | 2 |
| 3 | 4 | -4 |
| 4 | -8 | 8 |
| 5 | 16 | -16 |
+------+------+------+
WITH RECURSIVE fibonacci (n, fib_n, next_fib_n) AS
(
SELECT 1, 0, 1
UNION ALL
SELECT n + 1, next_fib_n, fib_n + next_fib_n
FROM fibonacci WHERE n < 10
)
SELECT * FROM fibonacci;
+------+-------+------------+
| n | fib_n | next_fib_n |
+------+-------+------------+
| 1 | 0 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 3 |
| 5 | 3 | 5 |
| 6 | 5 | 8 |
| 7 | 8 | 13 |
| 8 | 13 | 21 |
| 9 | 21 | 34 |
| 10 | 34 | 55 |
+------+-------+------------+
WITH RECURSIVE fibonacci (n, fib_n, next_fib_n) AS
(
SELECT 1, 0, 1
UNION ALL
SELECT n + 1, next_fib_n, fib_n + next_fib_n
FROM fibonacci WHERE n < 10
)
SELECT fib_n FROM fibonacci WHERE n = 8;
+-------+
| fib_n |
+-------+
| 13 |
+-------+
create table sales(date DATE,price NUMBER(7,2));
insert into sales values(str_to_date('2017-01-03', '%Y-%m-%d'),100);
insert into sales values(str_to_date('2017-01-03', '%Y-%m-%d'),200);
insert into sales values(str_to_date('2017-01-06', '%Y-%m-%d'),50);
insert into sales values(str_to_date('2017-01-08', '%Y-%m-%d'),10);
insert into sales values(str_to_date('2017-01-08', '%Y-%m-%d'),20);
insert into sales values(str_to_date('2017-01-08', '%Y-%m-%d'),150);
insert into sales values(str_to_date('2017-01-10', '%Y-%m-%d'),5);
SELECT * FROM sales ORDER BY date, price;
+------------+--------+
| date | price |
+------------+--------+
| 2017-01-03 | 100.00 |
| 2017-01-03 | 200.00 |
| 2017-01-06 | 50.00 |
| 2017-01-08 | 10.00 |
| 2017-01-08 | 20.00 |
| 2017-01-08 | 150.00 |
| 2017-01-10 | 5.00 |
+------------+--------+
SELECT date, SUM(price) AS sum_price
FROM sales
GROUP BY date
ORDER BY date;
+------------+-----------+
| date | sum_price |
+------------+-----------+
| 2017-01-03 | 300.00 |
| 2017-01-06 | 50.00 |
| 2017-01-08 | 180.00 |
| 2017-01-10 | 5.00 |
+------------+-----------+
WITH RECURSIVE dates (date) AS
(
SELECT MIN(date) FROM sales
UNION ALL
SELECT date + INTERVAL 1 DAY FROM dates
WHERE date + INTERVAL 1 DAY <= (SELECT MAX(date) FROM sales)
)
SELECT * FROM dates;
+------------+
| date |
+------------+
| 2017-01-03 |
| 2017-01-04 |
| 2017-01-05 |
| 2017-01-06 |
| 2017-01-07 |
| 2017-01-08 |
| 2017-01-09 |
| 2017-01-10 |
+------------+
WITH RECURSIVE dates (date) AS
(
SELECT MIN(date) FROM sales
UNION ALL
SELECT date + INTERVAL 1 DAY FROM dates
WHERE date + INTERVAL 1 DAY <= (SELECT MAX(date) FROM sales)
)
SELECT dates.date, COALESCE(SUM(price), 0) AS sum_price
FROM dates LEFT JOIN sales ON dates.date = sales.date
GROUP BY dates.date
ORDER BY dates.date;
+------------+-----------+
| date | sum_price |
+------------+-----------+
| 2017-01-03 | 300.00 |
| 2017-01-04 | 0.00 |
| 2017-01-05 | 0.00 |
| 2017-01-06 | 50.00 |
| 2017-01-07 | 0.00 |
| 2017-01-08 | 180.00 |
| 2017-01-09 | 0.00 |
| 2017-01-10 | 5.00 |
+------------+-----------+
################################################################################################
### PART 1 SQL syntax
################################################################################################
WITH cte1(txt) AS (SELECT "This "),
cte2(txt) AS (SELECT CONCAT(cte1.txt,"is a ") FROM cte1),
cte3(txt) AS (SELECT "nice query" UNION
SELECT "query that rocks" UNION
SELECT "query"),
cte4(txt) AS (SELECT concat(cte2.txt, cte3.txt) FROM cte2, cte3)
SELECT MAX(txt), MIN(txt) FROM cte4;
+----------------------------+----------------------+
| MAX(txt) | MIN(txt) |
+----------------------------+----------------------+
| This is a query that rocks | This is a nice query |
+----------------------------+----------------------+
WITH RECURSIVE my_cte AS
(
SELECT 1 AS n
UNION ALL
SELECT 1+n FROM my_cte WHERE n<10
)
SELECT * FROM my_cte;
+------+
| n |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+------+
CREATE TABLE numbers
WITH RECURSIVE my_cte(n) AS
(
SELECT 1
UNION ALL
SELECT 1+n FROM my_cte WHERE n<6
)
SELECT * FROM my_cte;
SELECT * FROM numbers;
+------+
| n |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
+------+
INSERT INTO numbers
WITH RECURSIVE my_cte(n) AS
(
SELECT 1
UNION ALL
SELECT 1+n FROM my_cte WHERE n<6
)
SELECT * FROM my_cte;
SELECT * FROM numbers;
+------+
| n |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
+------+
DELETE FROM numbers
WHERE numbers.n >
(
WITH RECURSIVE my_cte(n) AS
(
SELECT 1
UNION ALL
SELECT 1+n FROM my_cte WHERE n<6
)
SELECT AVG(n)/2 FROM my_cte
);
SELECT * FROM numbers;
+------+
| n |
+------+
| 1 |
| 1 |
+------+
################################################################################################
### PART 2 generating series
################################################################################################
WITH RECURSIVE my_cte AS
(
SELECT 1 as f, 1 as next_f
UNION ALL
SELECT next_f, f+next_f FROM my_cte WHERE f < 500
)
SELECT * FROM my_cte;
+------+--------+
| f | next_f |
+------+--------+
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 5 |
| 5 | 8 |
| 8 | 13 |
| 13 | 21 |
| 21 | 34 |
| 34 | 55 |
| 55 | 89 |
| 89 | 144 |
| 144 | 233 |
| 233 | 377 |
| 377 | 610 |
| 610 | 987 |
+------+--------+
WITH RECURSIVE
digits AS
(
SELECT '0' AS d UNION ALL SELECT '1'
),
strings AS
(
SELECT CAST('' AS CHAR(4)) AS s
UNION ALL
SELECT CONCAT(strings.s, digits.d)
FROM strings, digits
WHERE LENGTH(strings.s) < 4
)
SELECT * FROM strings WHERE LENGTH(s)=4;
+------+
| s |
+------+
| 0000 |
| 0001 |
| 0010 |
| 0011 |
| 0100 |
| 0101 |
| 0110 |
| 0111 |
| 1000 |
| 1001 |
| 1010 |
| 1011 |
| 1100 |
| 1101 |
| 1110 |
| 1111 |
+------+
################################################################################################
### PART 3 hierarchies
################################################################################################
CREATE TABLE category(
category_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
parent INT DEFAULT NULL
);
INSERT INTO category VALUES(1,'ELECTRONICS',NULL),(2,'TELEVISIONS',1),(3,'TUBE',2),
(4,'LCD',2),(5,'PLASMA',2),(6,'PORTABLE ELECTRONICS',1),(7,'MP3 PLAYERS',6),(8,'FLASH',7),
(9,'CD PLAYERS',6),(10,'2 WAY RADIOS',6);
SELECT * FROM category ORDER BY category_id;
+-------------+----------------------+--------+
| category_id | name | parent |
+-------------+----------------------+--------+
| 1 | ELECTRONICS | NULL |
| 2 | TELEVISIONS | 1 |
| 3 | TUBE | 2 |
| 4 | LCD | 2 |
| 5 | PLASMA | 2 |
| 6 | PORTABLE ELECTRONICS | 1 |
| 7 | MP3 PLAYERS | 6 |
| 8 | FLASH | 7 |
| 9 | CD PLAYERS | 6 |
| 10 | 2 WAY RADIOS | 6 |
+-------------+----------------------+--------+
#Retrieving a Full Tree
WITH RECURSIVE cte AS
(
# seed SELECT
SELECT category_id, name FROM category WHERE parent IS NULL
UNION ALL
# recursive SELECT
SELECT c.category_id, c.name FROM category c JOIN cte
ON cte.category_id=c.parent # find children
)
SELECT category_id, name FROM cte;
+-------------+----------------------+
| category_id | name |
+-------------+----------------------+
| 1 | ELECTRONICS |
| 6 | PORTABLE ELECTRONICS |
| 2 | TELEVISIONS |
| 10 | 2 WAY RADIOS |
| 9 | CD PLAYERS |
| 7 | MP3 PLAYERS |
| 5 | PLASMA |
| 4 | LCD |
| 3 | TUBE |
| 8 | FLASH |
+-------------+----------------------+
WITH RECURSIVE cte AS
(
SELECT category_id, name, 0 AS depth FROM category WHERE parent IS NULL
UNION ALL
SELECT c.category_id, c.name, cte.depth+1 FROM category c JOIN cte ON
cte.category_id=c.parent
)
SELECT * FROM cte ORDER BY depth;
+-------------+----------------------+-------+
| category_id | name | depth |
+-------------+----------------------+-------+
| 1 | ELECTRONICS | 0 |
| 6 | PORTABLE ELECTRONICS | 1 |
| 2 | TELEVISIONS | 1 |
| 10 | 2 WAY RADIOS | 2 |
| 9 | CD PLAYERS | 2 |
| 7 | MP3 PLAYERS | 2 |
| 5 | PLASMA | 2 |
| 4 | LCD | 2 |
| 3 | TUBE | 2 |
| 8 | FLASH | 3 |
+-------------+----------------------+-------+
WITH RECURSIVE cte AS
(
SELECT category_id, name, CAST(category_id AS CHAR(200)) AS path
FROM category WHERE parent IS NULL
UNION ALL
SELECT c.category_id, c.name, CONCAT(cte.path, ",", c.category_id)
FROM category c JOIN cte ON cte.category_id=c.parent
)
SELECT * FROM cte ORDER BY path;
+-------------+----------------------+---------+
| category_id | name | path |
+-------------+----------------------+---------+
| 1 | ELECTRONICS | 1 |
| 2 | TELEVISIONS | 1,2 |
| 3 | TUBE | 1,2,3 |
| 4 | LCD | 1,2,4 |
| 5 | PLASMA | 1,2,5 |
| 6 | PORTABLE ELECTRONICS | 1,6 |
| 10 | 2 WAY RADIOS | 1,6,10 |
| 7 | MP3 PLAYERS | 1,6,7 |
| 8 | FLASH | 1,6,7,8 |
| 9 | CD PLAYERS | 1,6,9 |
+-------------+----------------------+---------+
#Finding all the leaf nodes
SELECT category_id, name FROM category
WHERE category_id NOT IN
# IDs of all parents:
(SELECT parent FROM category WHERE parent IS NOT NULL);
+-------------+--------------+
| category_id | name |
+-------------+--------------+
| 3 | TUBE |
| 4 | LCD |
| 5 | PLASMA |
| 8 | FLASH |
| 9 | CD PLAYERS |
| 10 | 2 WAY RADIOS |
+-------------+--------------+
#Retrieving a Single Path
WITH RECURSIVE cte AS
(
SELECT name, parent FROM category WHERE name='FLASH'
UNION ALL
SELECT c.name, c.parent FROM category c JOIN cte
ON c.category_id=cte.parent # find parent
)
SELECT * FROM cte;
+----------------------+--------+
| name | parent |
+----------------------+--------+
| FLASH | 7 |
| MP3 PLAYERS | 6 |
| PORTABLE ELECTRONICS | 1 |
| ELECTRONICS | NULL |
+----------------------+--------+
WITH RECURSIVE cte AS
(
SELECT name, parent, 0 as depth FROM category WHERE name='FLASH'
UNION ALL
SELECT c.name, c.parent, cte.depth-1 FROM category c JOIN cte
ON c.category_id=cte.parent
)
SELECT * FROM cte ORDER BY depth;
+----------------------+--------+-------+
| name | parent | depth |
+----------------------+--------+-------+
| ELECTRONICS | NULL | -3 |
| PORTABLE ELECTRONICS | 1 | -2 |
| MP3 PLAYERS | 6 | -1 |
| FLASH | 7 | 0 |
+----------------------+--------+-------+
#Finding the Depth of the Nodes
WITH RECURSIVE cte AS
(
SELECT category_id, CAST(name AS CHAR(200)) AS name,
CAST(category_id AS CHAR(200)) AS path,
0 as depth
FROM category WHERE parent IS NULL
UNION ALL
SELECT c.category_id,
CONCAT(REPEAT(' ', cte.depth+1), c.name), # indentation
CONCAT(cte.path, ",", c.category_id),
cte.depth+1
FROM category c JOIN cte ON
cte.category_id=c.parent
)
SELECT * FROM cte ORDER BY path;
+-------------+-----------------------+---------+-------+
| category_id | name | path | depth |
+-------------+-----------------------+---------+-------+
| 1 | ELECTRONICS | 1 | 0 |
| 2 | TELEVISIONS | 1,2 | 1 |
| 3 | TUBE | 1,2,3 | 2 |
| 4 | LCD | 1,2,4 | 2 |
| 5 | PLASMA | 1,2,5 | 2 |
| 6 | PORTABLE ELECTRONICS | 1,6 | 1 |
| 10 | 2 WAY RADIOS | 1,6,10 | 2 |
| 7 | MP3 PLAYERS | 1,6,7 | 2 |
| 8 | FLASH | 1,6,7,8 | 3 |
| 9 | CD PLAYERS | 1,6,9 | 2 |
+-------------+-----------------------+---------+-------+
#Depth of a sub-tree
WITH RECURSIVE cte AS
(
SELECT category_id, name,
CAST(category_id AS CHAR(200)) AS path,
0 as depth
FROM category WHERE name='PORTABLE ELECTRONICS' # sub-tree root
UNION ALL
SELECT c.category_id,
c.name,
CONCAT(cte.path, ",", c.category_id),
cte.depth+1
FROM category c JOIN cte
ON cte.category_id=c.parent
)
SELECT * FROM cte ORDER BY path;
+-------------+----------------------+-------+-------+
| category_id | name | path | depth |
+-------------+----------------------+-------+-------+
| 6 | PORTABLE ELECTRONICS | 6 | 0 |
| 10 | 2 WAY RADIOS | 6,10 | 1 |
| 7 | MP3 PLAYERS | 6,7 | 1 |
| 8 | FLASH | 6,7,8 | 2 |
| 9 | CD PLAYERS | 6,9 | 1 |
+-------------+----------------------+-------+-------+
#Find the immediate subordinates of a node
WITH RECURSIVE cte AS
(
SELECT category_id, name, 0 as depth
FROM category WHERE name='PORTABLE ELECTRONICS'
UNION ALL
SELECT c.category_id, c.name, cte.depth+1
FROM category c JOIN cte
ON cte.category_id=c.parent
WHERE cte.depth=0
)
SELECT * FROM cte;
+-------------+----------------------+-------+
| category_id | name | depth |
+-------------+----------------------+-------+
| 6 | PORTABLE ELECTRONICS | 0 |
| 10 | 2 WAY RADIOS | 1 |
| 9 | CD PLAYERS | 1 |
| 7 | MP3 PLAYERS | 1 |
+-------------+----------------------+-------+
#Aggregate functions in a nested set
CREATE TABLE product(
category_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
parent INT DEFAULT NULL
);
INSERT INTO product VALUES(1,'ELECTRONICS',NULL),(2,'TELEVISIONS',1),(3,'TUBE',2),
(4,'LCD',2),(5,'PLASMA',2),(6,'PORTABLE ELECTRONICS',1),(7,'MP3 PLAYERS',6),(8,'FLASH',7),
(9,'CD PLAYERS',6),(10,'2 WAY RADIOS',6);
WITH RECURSIVE cte AS
(
SELECT c.category_id, c.name AS cat_name, c.parent, p.name AS prod_name
FROM category c JOIN product p ON c.category_id=p.category_id
UNION ALL
SELECT c.category_id, c.name, c.parent, cte.prod_name
FROM cte JOIN category c ON c.category_id=cte.parent
)
SELECT cat_name, COUNT(*) AS prod_in_cat FROM cte
GROUP BY cat_name;
+----------------------+-------------+
| cat_name | prod_in_cat |
+----------------------+-------------+
| ELECTRONICS | 10 |
| TELEVISIONS | 4 |
| TUBE | 1 |
| LCD | 1 |
| PLASMA | 1 |
| PORTABLE ELECTRONICS | 5 |
| MP3 PLAYERS | 2 |
| FLASH | 1 |
| CD PLAYERS | 1 |
| 2 WAY RADIOS | 1 |
+----------------------+-------------+
################################################################################################
### PART 4 depth-first or breadth-first traversal, transitive closure, cycle avoidance
################################################################################################
#Depth-first or breadth-first
CREATE TABLE tree (person CHAR(20), parent CHAR(20));
INSERT INTO tree VALUES
('Robert I', NULL),
('Thurimbert', 'Robert I'),
('Robert II', 'Thurimbert'),
('Cancor', 'Thurimbert'),
('Landrade', 'Thurimbert'),
('Ingramm', 'Thurimbert'),
('Robert III', 'Robert II'),
('Chaudegrand', 'Landrade'),
('Ermengarde', 'Ingramm');
WITH RECURSIVE descendants AS
(
SELECT person
FROM tree
WHERE person='Thurimbert'
UNION ALL
SELECT t.person
FROM descendants d, tree t
WHERE t.parent=d.person
)
SELECT * FROM descendants;
+-------------+
| person |
+-------------+
| Thurimbert |
| Ingramm |
| Landrade |
| Cancor |
| Robert II |
| Ermengarde |
| Chaudegrand |
| Robert III |
+-------------+
WITH RECURSIVE descendants AS
(
SELECT person, 1 as level
FROM tree
WHERE person='Thurimbert'
UNION ALL
SELECT t.person, d.level+1
FROM descendants d, tree t
WHERE t.parent=d.person
)
SELECT * FROM descendants ORDER BY level;
+-------------+-------+
| person | level |
+-------------+-------+
| Thurimbert | 1 |
| Ingramm | 2 |
| Landrade | 2 |
| Cancor | 2 |
| Robert II | 2 |
| Ermengarde | 3 |
| Chaudegrand | 3 |
| Robert III | 3 |
+-------------+-------+
WITH RECURSIVE descendants AS
(
SELECT person, CAST(person AS CHAR(500)) AS path
FROM tree
WHERE person='Thurimbert'
UNION ALL
SELECT t.person, CONCAT(d.path, ',', t.person)
FROM descendants d, tree t
WHERE t.parent=d.person
)
SELECT * FROM descendants ORDER BY path;
+-------------+---------------------------------+
| person | path |
+-------------+---------------------------------+
| Thurimbert | Thurimbert |
| Cancor | Thurimbert,Cancor |
| Ingramm | Thurimbert,Ingramm |
| Ermengarde | Thurimbert,Ingramm,Ermengarde |
| Landrade | Thurimbert,Landrade |
| Chaudegrand | Thurimbert,Landrade,Chaudegrand |
| Robert II | Thurimbert,Robert II |
| Robert III | Thurimbert,Robert II,Robert III |
+-------------+---------------------------------+
#Computing transitive closures with simple cycle avoidance
CREATE TABLE rockets
(origin CHAR(20), destination CHAR(20), trip_time INT);
INSERT INTO rockets VALUES
('Earth', 'Mars', 2),
('Mars', 'Jupiter', 3),
('Jupiter', 'Saturn', 4);
WITH RECURSIVE all_destinations AS
(
SELECT destination AS planet
FROM rockets
WHERE origin='Earth'
UNION ALL
SELECT r.destination
FROM rockets r, all_destinations d
WHERE r.origin=d.planet
)
SELECT * FROM all_destinations;
+---------+
| planet |
+---------+
| Mars |
| Jupiter |
| Saturn |
+---------+
INSERT INTO rockets VALUES ('Saturn', 'Earth', 9);
WITH RECURSIVE all_destinations AS
(
SELECT destination AS planet
FROM rockets
WHERE origin='Earth'
UNION ALL
SELECT r.destination
FROM rockets r, all_destinations d
WHERE r.origin=d.planet
)
SELECT * FROM all_destinations;
ERROR 5746 (HY000): cycle detected while executing recursive WITH query
#More complex cycle avoidance
WITH RECURSIVE all_destinations AS
(
SELECT destination AS planet, trip_time AS total_time,
CAST(destination AS CHAR(500)) AS path
FROM rockets
WHERE origin='Earth'
UNION ALL
SELECT r.destination, d.total_time+r.trip_time,
CONCAT(d.path, ',', r.destination)
FROM rockets r, all_destinations d
WHERE r.origin=d.planet
AND FIND_IN_SET(r.destination, d.path)=0
)
SELECT * FROM all_destinations;
+---------+------------+---------------------------+
| planet | total_time | path |
+---------+------------+---------------------------+
| Mars | 2 | Mars |
| Jupiter | 5 | Mars,Jupiter |
| Saturn | 9 | Mars,Jupiter,Saturn |
| Earth | 18 | Mars,Jupiter,Saturn,Earth |
+---------+------------+---------------------------+
WITH RECURSIVE all_destinations AS
(
SELECT destination AS planet, trip_time AS total_time,
CAST(destination AS CHAR(500)) AS path, 0 AS is_cycle
FROM rockets
WHERE origin='Earth'
UNION ALL
SELECT r.destination, d.total_time+r.trip_time,
CONCAT(d.path, ',', r.destination),
FIND_IN_SET(r.destination, d.path)!=0
FROM rockets r, all_destinations d
WHERE r.origin=d.planet
AND is_cycle=0
)
SELECT * FROM all_destinations;
+---------+------------+--------------------------------+----------+
| planet | total_time | path | is_cycle |
+---------+------------+--------------------------------+----------+
| Mars | 2 | Mars | 0 |
| Jupiter | 5 | Mars,Jupiter | 0 |
| Saturn | 9 | Mars,Jupiter,Saturn | 0 |
| Earth | 18 | Mars,Jupiter,Saturn,Earth | 0 |
| Mars | 20 | Mars,Jupiter,Saturn,Earth,Mars | 1 |
+---------+------------+--------------------------------+----------+

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
with cte1(c1, c2) as
(select 1, '0' from dual
union all select 2, '1' from dual
),
cte2(c1, c2) as
(select '0', 1 from dual
union all select cte1.c2, cte1.c1 from cte2, cte1 where 10 = cte2.c1)
select * from cte1;
+------+------+
| c1 | c2 |
+------+------+
| 1 | 0 |
| 2 | 1 |
+------+------+

View File

@ -0,0 +1,447 @@
drop table EMP,DEPT,emp1,emp2;
create table EMP (
EMPno number,
ENAME varchar(30),
JOB varchar(30),
MGR number(4),
HIREDATE date,
SAL number(7,2),
COMM number(7,2),
DEPTNO number(2)
) ;
create table DEPT(
DEPTNO number(2),
DNAME(45),
LOC varchar(39)
) ;
CREATE TABLE emp1 (
empno VARCHAR(4000) NOT NULL,
ename VARCHAR(14),
job VARCHAR(9),
mgr VARCHAR(4000),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2));
CREATE TABLE emp2 (
empno VARCHAR(4000) NOT NULL,
ename VARCHAR(14),
job VARCHAR(9),
mgr VARCHAR(4000),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2));
insert into EMP values (7369,'SMITH','CLERK',7902, str_to_date('1980-12-17','%Y-%m-%d'),800,NULL, 20) ;
INSERT INTO EMP VALUES (7499, 'ALLEN','SALESMAN',7698,str_to_date('1981-02-20','%Y-%m-%d'),1600,300,30) ;
INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698, str_to_date('1981-02-22','%Y-%m-%d'),1250, 500, 30) ;
INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839, str_to_date('1981-08-02','%Y-%m-%d'), 2975, NULL, 20) ;
INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN', 7698, str_to_date('1981-09-28','%Y-%m-%d'), 1250, 1400, 30) ;
INSERT INTO EMP VALUES (7698, 'BLAKE','MANAGER', 7839, str_to_date('1981-05-01','%Y-%m-%d'), 2850, NULL, 30) ;
INSERT INTO EMP VALUES (7782, 'CLARK','MANAGER', 7839, str_to_date('1981-06-09','%Y-%m-%d'), 2450, NULL, 10) ;
insert into EMP values (7788,'SCOTT','ANALYST', 7566, str_to_date('1987-08-19','%Y-%m-%d'), 3000, null, 20) ;
INSERT INTO EMP VALUES (7839, 'KING','PRESIDENT', NULL, str_to_date('1981-11-17','%Y-%m-%d'), 5000, NULL, 10) ;
INSERT INTO EMP VALUES (7844, 'TURNER','SALESMAN', 7698, str_to_date('1981-09-08','%Y-%m-%d'), 1500, 0, 30) ;
INSERT INTO EMP VALUES(7876, 'ADAMS','CLERK', 7788, str_to_date('1987-05-23','%Y-%m-%d'), 1100, NULL, 20) ;
INSERT INTO EMP VALUES(7900, 'JAMES', 'CLEARK', 7698, str_to_date('1981-12-03','%Y-%m-%d'), 950, NULL, 30) ;
INSERT INTO EMP VALUES(7902, 'FORD','ANALYST',7566, str_to_date('1981-12-03','%Y-%m-%d'), 3000, NULL, 20) ;
INSERT INTO EMP VALUES(7934,'MILLER','CLERK', 7782, str_to_date('1982-06-23','%Y-%m-%d'), 1300,NULL, 10) ;
INSERT INTO emp1 values (7369, 'SMITH', 'CLERK', 7902, str_to_date('1980-12-17', '%Y-%m-%d'), 800, null, 20);
INSERT INTO emp1 values (7499, 'ALLEN', 'SALESMAN', 7698, str_to_date('1981-02-20', '%Y-%m-%d'), 1600, 300, 30);
INSERT INTO emp1 values (7521, 'WARD', 'SALESMAN', 7698, str_to_date('1981-02-22', '%Y-%m-%d'), 1250, 500, 30);
INSERT INTO emp1 values (7566, 'JONES', 'MANAGER', 7839, str_to_date('1981-08-02', '%Y-%m-%d'), 2975, null, 20);
INSERT INTO emp1 values (7654, 'MARTIN', 'SALESMAN', 7698, str_to_date('1981-09-28', '%Y-%m-%d'), 1250, 1400, 30);
INSERT INTO emp1 values (7698, 'BLAKE', 'MANAGER', 7839, str_to_date('1981-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (7782, 'CLARK', 'MANAGER', 7839, str_to_date('1981-06-09' , '%Y-%m-%d'), 2450, null, 10);
INSERT INTO emp1 values (7788, 'SCOTT', 'ANALYST', 7566, str_to_date('1987-08-19', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7839, 'KING', 'PRESIDENT', null, str_to_date('1981-11-17', '%Y-%m-%d'), 5000, null, 10);
INSERT INTO emp1 values (7844, 'TURNER', 'SALESMAN', 7698, str_to_date('1981-09-08', '%Y-%m-%d'), 1500, 0, 30);
INSERT INTO emp1 values (7876, 'ADAMS', 'CLERK', 7788, str_to_date('1987-05-23', '%Y-%m-%d'), 1100, null, 20);
INSERT INTO emp1 values (7900, 'JAMES', 'CLERK', 7698, str_to_date('1981-12-03', '%Y-%m-%d'), 950, null, 30);
INSERT INTO emp1 values (7902, 'FORD', 'ANALYST', 7566, str_to_date('1981-12-03', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7934, 'MILLER', 'CLERK', 7782, str_to_date('1982-01-23', '%Y-%m-%d'), 1300, null, 10);
INSERT INTO emp1 values (LPAD('8100',400,'5'), 'Eve', 'MANAGER', 7839, str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8101',3000,'5'), 'Eve1', 'MANAGER', LPAD('8100',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8102',3000,'5'), 'Eve2', 'MANAGER', LPAD('8101',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8103',3000,'5'), 'Eve3', 'MANAGER', LPAD('8102',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8104',3000,'5'), 'Eve4', 'MANAGER', LPAD('8103',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8105',3000,'5'), 'Eve5', 'MANAGER', LPAD('8104',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8106',3000,'5'), 'Eve6', 'MANAGER', LPAD('8105',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8107',400,'5'), 'Eve7', 'MANAGER', LPAD('8106',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8108',400,'5'), 'Eve8', 'MANAGER', LPAD('8107',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8109',400,'5'), 'Eve9', 'MANAGER', LPAD('8108',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8110',400,'5'), 'Eve10', 'MANAGER', LPAD('8109',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8111',400,'5'), 'Eve11', 'MANAGER', LPAD('8110',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8112',400,'5'), 'Eve12', 'MANAGER', LPAD('8111',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8113',400,'5'), 'Eve13', 'MANAGER', LPAD('8112',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8114',400,'5'), 'Eve14', 'MANAGER', LPAD('8113',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8115',400,'5'), 'Eve15', 'MANAGER', LPAD('8114',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8116',400,'5'), 'Eve16', 'MANAGER', LPAD('8115',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8117',400,'5'), 'Eve17', 'MANAGER', LPAD('8116',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8118',400,'5'), 'Eve18', 'MANAGER', LPAD('8117',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8119',400,'5'), 'Eve19', 'CLERK', LPAD('8118',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp2 values (4002, 'SMITH', 'CLERK', 5002, str_to_date('1980-12-17', '%Y-%m-%d'), 800, null, 20);
INSERT INTO emp2 values (5003, 'ALLEN', 'SALESMAN', 6002, str_to_date('1981-02-20', '%Y-%m-%d'), 1600, 300, 30);
INSERT INTO emp2 values (5004, 'WARD', 'SALESMAN', 6002, str_to_date('1981-02-22', '%Y-%m-%d'), 1250, 500, 30);
INSERT INTO emp2 values (6001, 'JONES', 'MANAGER', 7839, str_to_date('1981-08-02', '%Y-%m-%d'), 2975, null, 20);
INSERT INTO emp2 values (5005, 'MARTIN', 'SALESMAN', 6002, str_to_date('1981-09-28', '%Y-%m-%d'), 1250, 1400, 30);
INSERT INTO emp2 values (6002, 'BLAKE', 'MANAGER', 7839, str_to_date('1981-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp2 values (6003, 'CLARK', 'MANAGER', 7839, str_to_date('1981-06-09' , '%Y-%m-%d'), 2450, null, 10);
INSERT INTO emp2 values (5001, 'SCOTT', 'ANALYST', 6001, str_to_date('1987-08-19', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp2 values (7839, 'KING', 'PRESIDENT', null, str_to_date('1987-11-17', '%Y-%m-%d'), 5000, null, 10);
INSERT INTO emp2 values (5006, 'TURNER', 'SALESMAN', 6002, str_to_date('1981-09-08', '%Y-%m-%d'), 1500, 0, 30);
INSERT INTO emp2 values (4001, 'ADAMS', 'CLERK', 5001, str_to_date('1987-05-23', '%Y-%m-%d'), 1100, null, 20);
INSERT INTO emp2 values (5007, 'JAMES', 'CLERK', 6002, str_to_date('1981-12-03', '%Y-%m-%d'), 950, null, 30);
INSERT INTO emp2 values (5002, 'FORD', 'ANALYST', 6001, str_to_date('1981-12-03', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp2 values (5008, 'MILLER', 'CLERK', 6003, str_to_date('1982-01-23', '%Y-%m-%d'), 1300, null, 10);
## =======================================================================
## Test Case 1:
## - recursive WITH Query: no cycle clause used in query in acyclic data
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
update emp set mgr = 7788 where ename = 'KING';
drop table emp1;
drop table emp2;
CREATE TABLE emp1 (
empno VARCHAR(4000) NOT NULL,
ename VARCHAR(14),
job VARCHAR(9),
mgr VARCHAR(4000),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2));
CREATE TABLE emp2 (
empno VARCHAR(4000) NOT NULL,
ename VARCHAR(14),
job VARCHAR(9),
mgr VARCHAR(4000),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2));
INSERT INTO emp1 values (7369, 'SMITH', 'CLERK', 7902, str_to_date('1980-12-17', '%Y-%m-%d'), 800, null, 20);
INSERT INTO emp1 values (7499, 'ALLEN', 'SALESMAN', 7698, str_to_date('1981-02-20', '%Y-%m-%d'), 1600, 300, 30);
INSERT INTO emp1 values (7521, 'WARD', 'SALESMAN', 7698, str_to_date('1981-02-22', '%Y-%m-%d'), 1250, 500, 30);
INSERT INTO emp1 values (7566, 'JONES', 'MANAGER', 7839, str_to_date('1981-08-02', '%Y-%m-%d'), 2975, null, 20);
INSERT INTO emp1 values (7654, 'MARTIN', 'SALESMAN', 7698, str_to_date('1981-09-28', '%Y-%m-%d'), 1250, 1400, 30);
INSERT INTO emp1 values (7698, 'BLAKE', 'MANAGER', 7839, str_to_date('1981-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (7782, 'CLARK', 'MANAGER', 7839, str_to_date('1981-06-09' , '%Y-%m-%d'), 2450, null, 10);
INSERT INTO emp1 values (7788, 'SCOTT', 'ANALYST', 7566, str_to_date('1987-08-19', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7839, 'KING', 'PRESIDENT', null, str_to_date('1981-11-17', '%Y-%m-%d'), 5000, null, 10);
INSERT INTO emp1 values (7844, 'TURNER', 'SALESMAN', 7698, str_to_date('1981-09-08', '%Y-%m-%d'), 1500, 0, 30);
INSERT INTO emp1 values (7876, 'ADAMS', 'CLERK', 7788, str_to_date('1987-05-23', '%Y-%m-%d'), 1100, null, 20);
INSERT INTO emp1 values (7900, 'JAMES', 'CLERK', 7698, str_to_date('1981-12-03', '%Y-%m-%d'), 950, null, 30);
INSERT INTO emp1 values (7902, 'FORD', 'ANALYST', 7566, str_to_date('1981-12-03', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7934, 'MILLER', 'CLERK', 7782, str_to_date('1982-01-23', '%Y-%m-%d'), 1300, null, 10);
INSERT INTO emp1 values (LPAD('8100',400,'5'), 'Eve', 'MANAGER', 7839, str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8101',3000,'5'), 'Eve1', 'MANAGER', LPAD('8100',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8102',3000,'5'), 'Eve2', 'MANAGER', LPAD('8101',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8103',3000,'5'), 'Eve3', 'MANAGER', LPAD('8102',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8104',3000,'5'), 'Eve4', 'MANAGER', LPAD('8103',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8105',3000,'5'), 'Eve5', 'MANAGER', LPAD('8104',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8106',3000,'5'), 'Eve6', 'MANAGER', LPAD('8105',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8107',400,'5'), 'Eve7', 'MANAGER', LPAD('8106',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8108',400,'5'), 'Eve8', 'MANAGER', LPAD('8107',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8109',400,'5'), 'Eve9', 'MANAGER', LPAD('8108',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8110',400,'5'), 'Eve10', 'MANAGER', LPAD('8109',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8111',400,'5'), 'Eve11', 'MANAGER', LPAD('8110',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8112',400,'5'), 'Eve12', 'MANAGER', LPAD('8111',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8113',400,'5'), 'Eve13', 'MANAGER', LPAD('8112',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8114',400,'5'), 'Eve14', 'MANAGER', LPAD('8113',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8115',400,'5'), 'Eve15', 'MANAGER', LPAD('8114',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8116',400,'5'), 'Eve16', 'MANAGER', LPAD('8115',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8117',400,'5'), 'Eve17', 'MANAGER', LPAD('8116',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8118',400,'5'), 'Eve18', 'MANAGER', LPAD('8117',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8119',400,'5'), 'Eve19', 'CLERK', LPAD('8118',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp2 values (4002, 'SMITH', 'CLERK', 5002, str_to_date('1980-12-17', '%Y-%m-%d'), 800, null, 20);
INSERT INTO emp2 values (5003, 'ALLEN', 'SALESMAN', 6002, str_to_date('1981-02-20', '%Y-%m-%d'), 1600, 300, 30);
INSERT INTO emp2 values (5004, 'WARD', 'SALESMAN', 6002, str_to_date('1981-02-22', '%Y-%m-%d'), 1250, 500, 30);
INSERT INTO emp2 values (6001, 'JONES', 'MANAGER', 7839, str_to_date('1981-08-02', '%Y-%m-%d'), 2975, null, 20);
INSERT INTO emp2 values (5005, 'MARTIN', 'SALESMAN', 6002, str_to_date('1981-09-28', '%Y-%m-%d'), 1250, 1400, 30);
INSERT INTO emp2 values (6002, 'BLAKE', 'MANAGER', 7839, str_to_date('1981-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp2 values (6003, 'CLARK', 'MANAGER', 7839, str_to_date('1981-06-09' , '%Y-%m-%d'), 2450, null, 10);
INSERT INTO emp2 values (5001, 'SCOTT', 'ANALYST', 6001, str_to_date('1987-08-19', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp2 values (7839, 'KING', 'PRESIDENT', null, str_to_date('1987-11-17', '%Y-%m-%d'), 5000, null, 10);
INSERT INTO emp2 values (5006, 'TURNER', 'SALESMAN', 6002, str_to_date('1981-09-08', '%Y-%m-%d'), 1500, 0, 30);
INSERT INTO emp2 values (4001, 'ADAMS', 'CLERK', 5001, str_to_date('1987-05-23', '%Y-%m-%d'), 1100, null, 20);
INSERT INTO emp2 values (5007, 'JAMES', 'CLERK', 6002, str_to_date('1981-12-03', '%Y-%m-%d'), 950, null, 30);
INSERT INTO emp2 values (5002, 'FORD', 'ANALYST', 6001, str_to_date('1981-12-03', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp2 values (5008, 'MILLER', 'CLERK', 6003, str_to_date('1982-01-23', '%Y-%m-%d'), 1300, null, 10);
--enable_warnings
## =======================================================================
## Test Case 2:
## - recursive WITH Query(Negative): cycle clause not used in query with
## cyclic data
## =======================================================================
/* add loop from scott back to king in emp */
update emp set mgr = 7788 where ename = 'KING';
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
ERROR 5746 (HY000): cycle detected while executing recursive WITH query
drop table emp1;
drop table emp2;
CREATE TABLE emp1 (
empno VARCHAR(4000) NOT NULL,
ename VARCHAR(14),
job VARCHAR(9),
mgr VARCHAR(4000),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2));
CREATE TABLE emp2 (
empno VARCHAR(4000) NOT NULL,
ename VARCHAR(14),
job VARCHAR(9),
mgr VARCHAR(4000),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2));
INSERT INTO emp1 values (7369, 'SMITH', 'CLERK', 7902, str_to_date('1980-12-17', '%Y-%m-%d'), 800, null, 20);
INSERT INTO emp1 values (7499, 'ALLEN', 'SALESMAN', 7698, str_to_date('1981-02-20', '%Y-%m-%d'), 1600, 300, 30);
INSERT INTO emp1 values (7521, 'WARD', 'SALESMAN', 7698, str_to_date('1981-02-22', '%Y-%m-%d'), 1250, 500, 30);
INSERT INTO emp1 values (7566, 'JONES', 'MANAGER', 7839, str_to_date('1981-08-02', '%Y-%m-%d'), 2975, null, 20);
INSERT INTO emp1 values (7654, 'MARTIN', 'SALESMAN', 7698, str_to_date('1981-09-28', '%Y-%m-%d'), 1250, 1400, 30);
INSERT INTO emp1 values (7698, 'BLAKE', 'MANAGER', 7839, str_to_date('1981-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (7782, 'CLARK', 'MANAGER', 7839, str_to_date('1981-06-09' , '%Y-%m-%d'), 2450, null, 10);
INSERT INTO emp1 values (7788, 'SCOTT', 'ANALYST', 7566, str_to_date('1987-08-19', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7839, 'KING', 'PRESIDENT', null, str_to_date('1981-11-17', '%Y-%m-%d'), 5000, null, 10);
INSERT INTO emp1 values (7844, 'TURNER', 'SALESMAN', 7698, str_to_date('1981-09-08', '%Y-%m-%d'), 1500, 0, 30);
INSERT INTO emp1 values (7876, 'ADAMS', 'CLERK', 7788, str_to_date('1987-05-23', '%Y-%m-%d'), 1100, null, 20);
INSERT INTO emp1 values (7900, 'JAMES', 'CLERK', 7698, str_to_date('1981-12-03', '%Y-%m-%d'), 950, null, 30);
INSERT INTO emp1 values (7902, 'FORD', 'ANALYST', 7566, str_to_date('1981-12-03', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7934, 'MILLER', 'CLERK', 7782, str_to_date('1982-01-23', '%Y-%m-%d'), 1300, null, 10);
INSERT INTO emp1 values (LPAD('8100',400,'5'), 'Eve', 'MANAGER', 7839, str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8101',3000,'5'), 'Eve1', 'MANAGER', LPAD('8100',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8102',3000,'5'), 'Eve2', 'MANAGER', LPAD('8101',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8103',3000,'5'), 'Eve3', 'MANAGER', LPAD('8102',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8104',3000,'5'), 'Eve4', 'MANAGER', LPAD('8103',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8105',3000,'5'), 'Eve5', 'MANAGER', LPAD('8104',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8106',3000,'5'), 'Eve6', 'MANAGER', LPAD('8105',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8107',400,'5'), 'Eve7', 'MANAGER', LPAD('8106',3000,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8108',400,'5'), 'Eve8', 'MANAGER', LPAD('8107',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8109',400,'5'), 'Eve9', 'MANAGER', LPAD('8108',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8110',400,'5'), 'Eve10', 'MANAGER', LPAD('8109',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8111',400,'5'), 'Eve11', 'MANAGER', LPAD('8110',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8112',400,'5'), 'Eve12', 'MANAGER', LPAD('8111',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8113',400,'5'), 'Eve13', 'MANAGER', LPAD('8112',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8114',400,'5'), 'Eve14', 'MANAGER', LPAD('8113',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8115',400,'5'), 'Eve15', 'MANAGER', LPAD('8114',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8116',400,'5'), 'Eve16', 'MANAGER', LPAD('8115',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8117',400,'5'), 'Eve17', 'MANAGER', LPAD('8116',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8118',400,'5'), 'Eve18', 'MANAGER', LPAD('8117',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (LPAD('8119',400,'5'), 'Eve19', 'CLERK', LPAD('8118',400,'5'), str_to_date('1984-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp2 values (4002, 'SMITH', 'CLERK', 5002, str_to_date('1980-12-17', '%Y-%m-%d'), 800, null, 20);
INSERT INTO emp2 values (5003, 'ALLEN', 'SALESMAN', 6002, str_to_date('1981-02-20', '%Y-%m-%d'), 1600, 300, 30);
INSERT INTO emp2 values (5004, 'WARD', 'SALESMAN', 6002, str_to_date('1981-02-22', '%Y-%m-%d'), 1250, 500, 30);
INSERT INTO emp2 values (6001, 'JONES', 'MANAGER', 7839, str_to_date('1981-08-02', '%Y-%m-%d'), 2975, null, 20);
INSERT INTO emp2 values (5005, 'MARTIN', 'SALESMAN', 6002, str_to_date('1981-09-28', '%Y-%m-%d'), 1250, 1400, 30);
INSERT INTO emp2 values (6002, 'BLAKE', 'MANAGER', 7839, str_to_date('1981-05-01', '%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp2 values (6003, 'CLARK', 'MANAGER', 7839, str_to_date('1981-06-09' , '%Y-%m-%d'), 2450, null, 10);
INSERT INTO emp2 values (5001, 'SCOTT', 'ANALYST', 6001, str_to_date('1987-08-19', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp2 values (7839, 'KING', 'PRESIDENT', null, str_to_date('1987-11-17', '%Y-%m-%d'), 5000, null, 10);
INSERT INTO emp2 values (5006, 'TURNER', 'SALESMAN', 6002, str_to_date('1981-09-08', '%Y-%m-%d'), 1500, 0, 30);
INSERT INTO emp2 values (4001, 'ADAMS', 'CLERK', 5001, str_to_date('1987-05-23', '%Y-%m-%d'), 1100, null, 20);
INSERT INTO emp2 values (5007, 'JAMES', 'CLERK', 6002, str_to_date('1981-12-03', '%Y-%m-%d'), 950, null, 30);
INSERT INTO emp2 values (5002, 'FORD', 'ANALYST', 6001, str_to_date('1981-12-03', '%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp2 values (5008, 'MILLER', 'CLERK', 6003, str_to_date('1982-01-23', '%Y-%m-%d'), 1300, null, 10);
update emp2 set mgr = 5001 where ename = 'KING';
## =======================================================================
## Test Case 3:
## - recursive WITH Query: Cycle Pruning with Cycle clause not used in the query
## Pruning predicate added that results in no cycles e.mgr < e.empno
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp2 e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM rw r, emp2 e
WHERE r.empno = e.mgr and e.mgr < e.empno
)
SELECT ename, empno, mgr
FROM rw;
+-------+-------+------+
| ename | empno | mgr |
+-------+-------+------+
| KING | 7839 | 5001 |
+-------+-------+------+
## =======================================================================
## Test Case 4:
## - recursive WITH Query: Cycle Pruning with Cycle clause not used in the query
## Pruning predicate added that results in no cycles e.mgr > e.empno
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp2 e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM rw r, emp2 e
WHERE r.empno = e.mgr and e.mgr > e.empno
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | 5001 |
| CLARK | 6003 | 7839 |
| BLAKE | 6002 | 7839 |
| JONES | 6001 | 7839 |
| MILLER | 5008 | 6003 |
| JAMES | 5007 | 6002 |
| TURNER | 5006 | 6002 |
| MARTIN | 5005 | 6002 |
| WARD | 5004 | 6002 |
| ALLEN | 5003 | 6002 |
| FORD | 5002 | 6001 |
| SCOTT | 5001 | 6001 |
| SMITH | 4002 | 5002 |
| ADAMS | 4001 | 5001 |
+--------+-------+------+
## =======================================================================
## Test Case 5:
## - recursive WITH Query: Cycle Pruning with Cycle clause not used in the query
## Pruning predicate added that results in no cycles r.empno < e.empno
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp2 e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM rw r, emp2 e
WHERE r.empno = e.mgr and r.empno < e.empno
)
SELECT ename, empno, mgr
FROM rw;
+-------+-------+------+
| ename | empno | mgr |
+-------+-------+------+
| KING | 7839 | 5001 |
+-------+-------+------+
## =======================================================================
## Test Case 6:
## - recursive WITH Query: Cycle Pruning with Cycle clause not used in the query
## Pruning predicate added that results in no cycles r.empno > e.empno
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp2 e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM rw r, emp2 e
WHERE r.empno = e.mgr and r.empno > e.empno
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | 5001 |
| CLARK | 6003 | 7839 |
| BLAKE | 6002 | 7839 |
| JONES | 6001 | 7839 |
| MILLER | 5008 | 6003 |
| JAMES | 5007 | 6002 |
| TURNER | 5006 | 6002 |
| MARTIN | 5005 | 6002 |
| WARD | 5004 | 6002 |
| ALLEN | 5003 | 6002 |
| FORD | 5002 | 6001 |
| SCOTT | 5001 | 6001 |
| SMITH | 4002 | 5002 |
| ADAMS | 4001 | 5001 |
+--------+-------+------+

View File

@ -0,0 +1,675 @@
drop table EMP;
create table EMP (
EMPno number,
ENAME VARCHAR(30),
JOB VARCHAR(30),
MGR number(4),
HIREDATE date,
SAL number(7,2),
COMM number(7,2),
DEPTNO number(2)
) ;
INSERT INTO EMP values (7369,'SMITH','CLERK',7902, str_to_date('1980-12-17','%Y-%m-%d'),800,NULL, 20) ;
INSERT INTO EMP VALUES (7499, 'ALLEN','SALESMAN',7698,str_to_date('1981-02-20','%Y-%m-%d'),1600,300,30) ;
INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698, str_to_date('1981-02-22','%Y-%m-%d'),1250, 500, 30) ;
INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839, str_to_date('1981-08-02','%Y-%m-%d'), 2975, NULL, 20) ;
INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN', 7698, str_to_date('1981-09-28','%Y-%m-%d'), 1250, 1400, 30) ;
INSERT INTO EMP VALUES (7698, 'BLAKE','MANAGER', 7839, str_to_date('1981-05-01','%Y-%m-%d'), 2850, NULL, 30) ;
INSERT INTO EMP VALUES (7782, 'CLARK','MANAGER', 7839, str_to_date('1981-06-09','%Y-%m-%d'), 2450, NULL, 10) ;
insert into EMP values (7788,'SCOTT','ANALYST', 7566, str_to_date('1987-08-19','%Y-%m-%d'), 3000, null, 20) ;
INSERT INTO EMP VALUES (7839, 'KING','PRESIDENT', NULL, str_to_date('1981-11-17','%Y-%m-%d'), 5000, NULL, 10) ;
INSERT INTO EMP VALUES (7844, 'TURNER','SALESMAN', 7698, str_to_date('1981-09-08','%Y-%m-%d'), 1500, 0, 30) ;
INSERT INTO EMP VALUES(7876, 'ADAMS','CLERK', 7788, str_to_date('1987-05-23','%Y-%m-%d'), 1100, NULL, 20) ;
INSERT INTO EMP VALUES(7900, 'JAMES', 'CLEARK', 7698, str_to_date('1981-12-03','%Y-%m-%d'), 950, NULL, 30) ;
INSERT INTO EMP VALUES(7902, 'FORD','ANALYST',7566, str_to_date('1981-12-03','%Y-%m-%d'), 3000, NULL, 20) ;
INSERT INTO EMP VALUES(7934,'MILLER','CLERK', 7782, str_to_date('1982-01-23','%Y-%m-%d'), 1300,NULL, 10) ;
drop table emp1;
CREATE TABLE emp1 (
empno VARCHAR(4000) NOT NULL,
ename VARCHAR(14),
job VARCHAR(9),
mgr VARCHAR(4000),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2));
INSERT INTO emp1 values (7369, 'SMITH', 'CLERK', 7902, str_to_date('1980-12-17',
'%Y-%m-%d'), 800, null, 20);
INSERT INTO emp1 values (7499, 'ALLEN', 'SALESMAN', 7698, str_to_date('1981-02-20', '%Y-%m-%d'), 1600, 300, 30);
INSERT INTO emp1 values (7521, 'WARD', 'SALESMAN', 7698, str_to_date('1981-02-22',
'%Y-%m-%d'), 1250, 500, 30);
INSERT INTO emp1 values (7566, 'JONES', 'MANAGER', 7839, str_to_date('1981-08-02',
'%Y-%m-%d'), 2975, null, 20);
INSERT INTO emp1 values (7654, 'MARTIN', 'SALESMAN', 7698, str_to_date('1981-09-28', '%Y-%m-%d'), 1250, 1400, 30);
INSERT INTO emp1 values (7698, 'BLAKE', 'MANAGER', 7839, str_to_date('1981-05-01',
'%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (7782, 'CLARK', 'MANAGER', 7839, str_to_date('1981-06-09'
, '%Y-%m-%d'), 2450, null, 10);
INSERT INTO emp1 values (7788, 'SCOTT', 'ANALYST', 7566, str_to_date('1987-08-19',
'%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7839, 'KING', 'PRESIDENT', null, str_to_date('1981-11-17', '%Y-%m-%d'), 5000, null, 10);
INSERT INTO emp1 values (7844, 'TURNER', 'SALESMAN', 7698, str_to_date('1981-09-08', '%Y-%m-%d'), 1500, 0, 30);
INSERT INTO emp1 values (7876, 'ADAMS', 'CLERK', 7788, str_to_date('1987-05-23',
'%Y-%m-%d'), 1100, null, 20);
INSERT INTO emp1 values (7900, 'JAMES', 'CLERK', 7698, str_to_date('1981-12-03',
'%Y-%m-%d'), 950, null, 30);
INSERT INTO emp1 values (7902, 'FORD', 'ANALYST', 7566, str_to_date('1981-12-03',
'%Y-%m-%d'), 3000, null, 20);
INSERT INTO emp1 values (7934, 'MILLER', 'CLERK', 7782, str_to_date('1982-01-23',
'%Y-%m-%d'), 1300, null, 10);
INSERT INTO emp1 values (8100, 'Eve', 'MANAGER', 7839, str_to_date('1984-05-01',
'%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (8101, 'Eve1', 'MANAGER', 8100, str_to_date('1984-05-01',
'%Y-%m-%d'), 2850, null, 30);
INSERT INTO emp1 values (8108, 'Eve8', 'CLERK', 8101, str_to_date('1984-05-01',
'%Y-%m-%d'), 2850, null, 30);
result_format: 4
## =======================================================================
## Test Case 1:
## - recursive WITH Query: Nested Loop Join
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT /*+ USE_NL(r e) */ e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 2:
## - recursive WITH Query: SORT MERGE Join
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT /*+ USE_MERGE(r e) */ e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 3:
## - recursive WITH Query: Hash Join
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT /*+ USE_HASH(r e) */ e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 4:
## - recursive WITH Query: Join in Initialisation Branch
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT /*+ USE_NL(e d) */ e.ename, e.mgr, e.empno
FROM emp e, emp d
WHERE e.sal = d. sal
UNION ALL
SELECT /*+ USE_HASH(r e) */ e.ename, e.mgr, e.empno
FROM rw r, emp e, emp d
WHERE r.empno = e.mgr and e.sal = d.sal
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| SMITH | 7369 | 7902 |
| ALLEN | 7499 | 7698 |
| WARD | 7521 | 7698 |
| WARD | 7521 | 7698 |
| JONES | 7566 | 7839 |
| MARTIN | 7654 | 7698 |
| MARTIN | 7654 | 7698 |
| BLAKE | 7698 | 7839 |
| CLARK | 7782 | 7839 |
| SCOTT | 7788 | 7566 |
| SCOTT | 7788 | 7566 |
| KING | 7839 | NULL |
| TURNER | 7844 | 7698 |
| ADAMS | 7876 | 7788 |
| JAMES | 7900 | 7698 |
| FORD | 7902 | 7566 |
| FORD | 7902 | 7566 |
| MILLER | 7934 | 7782 |
| WARD | 7521 | 7698 |
| SMITH | 7369 | 7902 |
| SMITH | 7369 | 7902 |
| JONES | 7566 | 7839 |
| BLAKE | 7698 | 7839 |
| CLARK | 7782 | 7839 |
| ADAMS | 7876 | 7788 |
| ADAMS | 7876 | 7788 |
| MILLER | 7934 | 7782 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| WARD | 7521 | 7698 |
| MARTIN | 7654 | 7698 |
| MARTIN | 7654 | 7698 |
| TURNER | 7844 | 7698 |
| JAMES | 7900 | 7698 |
| SCOTT | 7788 | 7566 |
| SCOTT | 7788 | 7566 |
| FORD | 7902 | 7566 |
| FORD | 7902 | 7566 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SCOTT | 7788 | 7566 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| MILLER | 7934 | 7782 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
| ADAMS | 7876 | 7788 |
| SMITH | 7369 | 7902 |
| SMITH | 7369 | 7902 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 6:
## - recursive WITH Query: Hash Join without using hints
## Static input on build side and fits in memory
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM emp e, rw r
WHERE e.mgr = r.empno
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 7:
## - recursive WITH Query: Hash Join without using hints
## Static input on probe side and fits in memory
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## 测试8-15都是在测试join的顺序或者hint的顺序
## Test Case 8:
## - recursive WITH Query: Join Order tests
## pump >< emp >< emp1
## =======================================================================
WITH rw (empno, mgr, iters, sal) AS
(
SELECT e.empno, e.mgr, 1, e.sal
FROM emp e, emp1 n1, emp1 n2
WHERE e.empno = n1.empno and e.mgr = n2.empno and e.empno < e.mgr
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */r.empno, e.mgr, r.iters + 1, r.sal + e.sal
FROM rw r, emp e, emp1 n
WHERE r.mgr = e.empno and e.mgr = n.empno and e.empno < e.mgr
)
SELECT *
FROM rw
ORDER BY 1, 3;
+-------+------+-------+---------+
| empno | mgr | iters | sal |
+-------+------+-------+---------+
| 7369 | 7902 | 1 | 800.00 |
| 7499 | 7698 | 1 | 1600.00 |
| 7499 | 7839 | 2 | 4450.00 |
| 7521 | 7698 | 1 | 1250.00 |
| 7521 | 7839 | 2 | 4100.00 |
| 7566 | 7839 | 1 | 2975.00 |
| 7654 | 7698 | 1 | 1250.00 |
| 7654 | 7839 | 2 | 4100.00 |
| 7698 | 7839 | 1 | 2850.00 |
| 7782 | 7839 | 1 | 2450.00 |
+-------+------+-------+---------+
## =======================================================================
## Test Case 9:
## - recursive WITH Query: Join Order tests
## emp >< pump >< emp1
## =======================================================================
WITH rw (empno, mgr, iters, sal) AS
(
SELECT e.empno, e.mgr, 1, e.sal
FROM emp e, emp1 n1, emp1 n2
WHERE e.empno = n1.empno and e.mgr = n2.empno and e.empno < e.mgr
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */r.empno, e.mgr, r.iters + 1, r.sal + e.sal
FROM emp e, rw r, emp1 n
WHERE e.empno = r.mgr and e.mgr = n.empno and e.empno < e.mgr
)
SELECT *
FROM rw
ORDER BY 1, 3;
+-------+------+-------+---------+
| empno | mgr | iters | sal |
+-------+------+-------+---------+
| 7369 | 7902 | 1 | 800.00 |
| 7499 | 7698 | 1 | 1600.00 |
| 7499 | 7839 | 2 | 4450.00 |
| 7521 | 7698 | 1 | 1250.00 |
| 7521 | 7839 | 2 | 4100.00 |
| 7566 | 7839 | 1 | 2975.00 |
| 7654 | 7698 | 1 | 1250.00 |
| 7654 | 7839 | 2 | 4100.00 |
| 7698 | 7839 | 1 | 2850.00 |
| 7782 | 7839 | 1 | 2450.00 |
+-------+------+-------+---------+
## =======================================================================
## Test Case 10:
## - recursive WITH Query: Join Order tests
## emp >< emp1 >< pump
## =======================================================================
WITH rw (empno, mgr, iters, sal) AS
(
SELECT e.empno, e.mgr, 1, e.sal
FROM emp e, emp1 n1, emp1 n2
WHERE e.empno = n1.empno and e.mgr = n2.empno and e.empno < e.mgr
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */r.empno, e.mgr, r.iters + 1, r.sal + e.sal
FROM emp e, emp1 n, rw r
WHERE e.mgr = n.empno and e.empno = r.mgr and e.empno < e.mgr
)
SELECT *
FROM rw
ORDER BY 1, 3;
+-------+------+-------+---------+
| empno | mgr | iters | sal |
+-------+------+-------+---------+
| 7369 | 7902 | 1 | 800.00 |
| 7499 | 7698 | 1 | 1600.00 |
| 7499 | 7839 | 2 | 4450.00 |
| 7521 | 7698 | 1 | 1250.00 |
| 7521 | 7839 | 2 | 4100.00 |
| 7566 | 7839 | 1 | 2975.00 |
| 7654 | 7698 | 1 | 1250.00 |
| 7654 | 7839 | 2 | 4100.00 |
| 7698 | 7839 | 1 | 2850.00 |
| 7782 | 7839 | 1 | 2450.00 |
+-------+------+-------+---------+
## =======================================================================
## Test Case 11:
## - recursive WITH Query: Join Order tests
## emp1 >< emp >< pump
## =======================================================================
WITH rw (empno, mgr, iters, sal) AS
(
SELECT e.empno, e.mgr, 1, e.sal
FROM emp e, emp1 n1, emp1 n2
WHERE e.empno = n1.empno and e.mgr = n2.empno and e.empno < e.mgr
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */r.empno, e.mgr, r.iters + 1, r.sal + e.sal
FROM emp1 n, emp e, rw r
WHERE n.empno = e.mgr and e.empno = r.mgr and e.empno < e.mgr
)
SELECT *
FROM rw
ORDER BY 1, 3;
+-------+------+-------+---------+
| empno | mgr | iters | sal |
+-------+------+-------+---------+
| 7369 | 7902 | 1 | 800.00 |
| 7499 | 7698 | 1 | 1600.00 |
| 7499 | 7839 | 2 | 4450.00 |
| 7521 | 7698 | 1 | 1250.00 |
| 7521 | 7839 | 2 | 4100.00 |
| 7566 | 7839 | 1 | 2975.00 |
| 7654 | 7698 | 1 | 1250.00 |
| 7654 | 7839 | 2 | 4100.00 |
| 7698 | 7839 | 1 | 2850.00 |
| 7782 | 7839 | 1 | 2450.00 |
+-------+------+-------+---------+
## =======================================================================
## Test Case 12:
## - recursive WITH Query: Join Order tests
## pump >< emp
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */ e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 13:
## - recursive WITH Query: Join Order tests
## emp >< pump
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */ e.ename, e.mgr, e.empno
FROM emp e, rw r
WHERE e.mgr = r.empno
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 14:
## - recursive WITH Query: Join Order tests
## emp1 >< pump >< emp
## =======================================================================
WITH rw (empno, mgr, iters, sal) AS
(
SELECT e.empno, e.mgr, 1, e.sal
FROM emp e, emp1 n1, emp1 n2
WHERE e.empno = n1.empno and e.mgr = n2.empno and e.empno < e.mgr
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */r.empno, e.mgr, r.iters + 1, r.sal + e.sal
FROM emp1 n, rw r, emp e
WHERE n.empno = e.mgr and r.mgr = e.empno and e.empno < e.mgr
)
SELECT *
FROM rw
ORDER BY 1, 3;
+-------+------+-------+---------+
| empno | mgr | iters | sal |
+-------+------+-------+---------+
| 7369 | 7902 | 1 | 800.00 |
| 7499 | 7698 | 1 | 1600.00 |
| 7499 | 7839 | 2 | 4450.00 |
| 7521 | 7698 | 1 | 1250.00 |
| 7521 | 7839 | 2 | 4100.00 |
| 7566 | 7839 | 1 | 2975.00 |
| 7654 | 7698 | 1 | 1250.00 |
| 7654 | 7839 | 2 | 4100.00 |
| 7698 | 7839 | 1 | 2850.00 |
| 7782 | 7839 | 1 | 2450.00 |
+-------+------+-------+---------+
## =======================================================================
## Test Case 15:
## - recursive WITH Query: Join Order tests
## pump >< emp1 >< emp
## =======================================================================
WITH rw (empno, mgr, iters, sal) AS
(
SELECT e.empno, e.mgr, 1, e.sal
FROM emp e, emp1 n1, emp1 n2
WHERE e.empno = n1.empno and e.mgr = n2.empno and e.empno < e.mgr
UNION ALL
SELECT /*+ ORDERED USE_HASH (r e) */r.empno, e.mgr, r.iters + 1, r.sal + e.sal
FROM rw r, emp1 n, emp e
WHERE r.mgr = e.empno and n.empno = e.mgr and e.empno < e.mgr
)
SELECT *
FROM rw
ORDER BY 1, 3;
+-------+------+-------+---------+
| empno | mgr | iters | sal |
+-------+------+-------+---------+
| 7369 | 7902 | 1 | 800.00 |
| 7499 | 7698 | 1 | 1600.00 |
| 7499 | 7839 | 2 | 4450.00 |
| 7521 | 7698 | 1 | 1250.00 |
| 7521 | 7839 | 2 | 4100.00 |
| 7566 | 7839 | 1 | 2975.00 |
| 7654 | 7698 | 1 | 1250.00 |
| 7654 | 7839 | 2 | 4100.00 |
| 7698 | 7839 | 1 | 2850.00 |
| 7782 | 7839 | 1 | 2450.00 |
+-------+------+-------+---------+
## =======================================================================
## Test Case 16:
## - recursive WITH Query: Join Skew handling. No local filter
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT /*+ PQ_SKEW (r) */ e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MILLER | 7934 | 7782 |
| JAMES | 7900 | 7698 |
| TURNER | 7844 | 7698 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
| FORD | 7902 | 7566 |
| SCOTT | 7788 | 7566 |
| SMITH | 7369 | 7902 |
| ADAMS | 7876 | 7788 |
+--------+-------+------+
## =======================================================================
## Test Case 17:
## - recursive WITH Query: Join Skew handling with an additional local filter
## =======================================================================
WITH rw (ename, mgr, empno) AS
(
SELECT ename, mgr, empno
FROM emp e
WHERE job = 'PRESIDENT'
UNION ALL
SELECT /*+ PQ_SKEW (r) */ e.ename, e.mgr, e.empno
FROM rw r, emp e
WHERE r.empno = e.mgr and e.empno < e.mgr
)
SELECT ename, empno, mgr
FROM rw;
+--------+-------+------+
| ename | empno | mgr |
+--------+-------+------+
| KING | 7839 | NULL |
| CLARK | 7782 | 7839 |
| BLAKE | 7698 | 7839 |
| JONES | 7566 | 7839 |
| MARTIN | 7654 | 7698 |
| WARD | 7521 | 7698 |
| ALLEN | 7499 | 7698 |
+--------+-------+------+

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
drop database if exists ctetest;
create database ctetest;
use ctetest;
create table EMP (
EMPno number,
ENAME varchar(30),
JOB varchar(30),
MGR number(4),
HIREDATE date,
SAL number(7,2),
COMM number(7,2),
DEPTNO number(2)
) ;
create table DEPT(
DEPTNO number(2),
DNAME char(45),
LOC varchar(39)
) ;
insert into EMP values (7369,'SMITH','CLERK',7902, str_to_date('17-DEC-80','%d-%b-%Y'),800,NULL, 20) ;
INSERT INTO EMP VALUES (7499, 'ALLEN','SALESMAN',7698,str_to_date('20-FEB-81','%d-%b-%Y'),1600,300,30) ;
INSERT INTO EMP VALUES (7521,'WARD','SALESMAN',7698, str_to_date('22-FEB-81','%d-%b-%Y'),1250, 500, 30) ;
INSERT INTO EMP VALUES (7566,'JONES','MANAGER',7839, str_to_date('02-APR-81','%d-%b-%Y'), 2975, NULL, 20) ;
INSERT INTO EMP VALUES (7654,'MARTIN','SALESMAN', 7698, str_to_date('28-SEP-81','%d-%b-%Y'), 1250, 1400, 30) ;
INSERT INTO EMP VALUES (7698, 'BLAKE','MANAGER', 7839, str_to_date('01-MAY-81','%d-%b-%Y'), 2850, NULL, 30) ;
INSERT INTO EMP VALUES (7782, 'CLARK','MANAGER', 7839, str_to_date('09-JUN-81','%d-%b-%Y'), 2450, NULL, 10) ;
insert into EMP values (7788,'SCOTT','ANALYST', 7566, str_to_date('19-APR-87','%d-%b-%Y'), 3000, null, 20) ;
INSERT INTO EMP VALUES (7839, 'KING','PRESIDENT', NULL, str_to_date('17-NOV-81','%d-%b-%Y'), 5000, NULL, 10) ;
INSERT INTO EMP VALUES (7844, 'TURNER','SALESMAN', 7698, str_to_date('08-SEP-81','%d-%b-%Y'), 1500, 0, 30) ;
INSERT INTO EMP VALUES(7876, 'ADAMS','CLERK', 7788, str_to_date('23-MAY-87','%d-%b-%Y'), 1100, NULL, 20) ;
INSERT INTO EMP VALUES(7900, 'JAMES', 'CLEARK', 7698, str_to_date('03-DEC-81','%d-%b-%Y'), 950, NULL, 30) ;
INSERT INTO EMP VALUES(7902, 'FORD','ANALYST',7566, str_to_date('03-DEC-81','%d-%b-%Y'), 3000, NULL, 20) ;
INSERT INTO EMP VALUES(7934,'MILLER','CLERK', 7782, str_to_date('23-JAN-82','%d-%b-%Y'), 1300,NULL, 10) ;
result_format: 4
## =======================================================================
## Test Case 1:
## - recursive WITH Query: Optimization on query with outside filter.
## Predicate pushdown optimization on static value job.
## The plan should reflect optimization or development can provide
## parameter to show that pushdown optimization happened for init branch
## =======================================================================
explain basic
WITH rw (ename, mgr, empno, job) AS
(
SELECT ename, mgr, empno, job
FROM emp e
UNION ALL
SELECT e.ename, e.mgr, e.empno, e.job
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT ename, empno, mgr, job
FROM rw
WHERE job = 'PRESIDENT' ;
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ==============================
|ID|OPERATOR |NAME|
------------------------------
|0 |SUBPLAN SCAN |rw |
|1 | RECURSIVE UNION ALL| |
|2 | TABLE SCAN |e |
|3 | HASH JOIN | |
|4 | TABLE SCAN |e |
|5 | TABLE SCAN |r |
==============================
Outputs & filters:
-------------------------------------
0 - output([rw.ename], [rw.empno], [rw.mgr], [rw.job]), filter([rw.job = 'PRESIDENT']),
access([rw.job], [rw.ename], [rw.empno], [rw.mgr])
1 - output([UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])]), filter(nil)
2 - output([e.ENAME], [e.MGR], [e.EMPno], [e.JOB]), filter(nil),
access([e.ENAME], [e.MGR], [e.EMPno], [e.JOB]), partitions(p0)
3 - output([e.ENAME], [e.MGR], [e.EMPno], [e.JOB]), filter(nil),
equal_conds([r.empno = e.MGR]), other_conds(nil)
4 - output([e.MGR], [e.ENAME], [e.EMPno], [e.JOB]), filter(nil),
access([e.MGR], [e.ENAME], [e.EMPno], [e.JOB]), partitions(p0)
5 - output([r.empno]), filter(nil),
access([r.empno]), partitions(nil)
|
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
WITH rw (ename, mgr, empno, job) AS
(
SELECT ename, mgr, empno, job
FROM emp e
UNION ALL
SELECT e.ename, e.mgr, e.empno, e.job
FROM rw r, emp e
WHERE r.empno = e.mgr
)
SELECT /*+ :HINT: */ ename, empno, mgr, job
FROM rw
WHERE job = 'PRESIDENT' ;
+-------+-------+------+-----------+
| ename | empno | mgr | job |
+-------+-------+------+-----------+
| KING | 7839 | NULL | PRESIDENT |
+-------+-------+------+-----------+