mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
2329 lines
58 KiB
Text
2329 lines
58 KiB
Text
create table t1 (a int, b varchar(32));
|
|
insert into t1 values
|
|
(4,'aaaa' ), (7,'bb'), (1,'ccc'), (4,'dd');
|
|
insert into t1 values
|
|
(3,'eee'), (7,'bb'), (1,'fff'), (4,'ggg');
|
|
with recursive
|
|
t as
|
|
(
|
|
select * from t1 where t1.b >= 'c'
|
|
union
|
|
select * from r
|
|
),
|
|
r as
|
|
(
|
|
select * from t
|
|
union
|
|
select t1.* from t1,r where r.a+1 = t1.a
|
|
)
|
|
select * from r;
|
|
ERROR HY000: Unacceptable mutual recursion with anchored table 't'
|
|
with recursive
|
|
a1(a,b) as
|
|
(select * from t1 where t1.a>3
|
|
union
|
|
select * from b1 where b1.a >3
|
|
union
|
|
select * from c1 where c1.a>3),
|
|
b1(a,b) as
|
|
(select * from a1 where a1.b > 'ccc'
|
|
union
|
|
select * from c1 where c1.b > 'ddd'),
|
|
c1(a,b) as
|
|
(select * from a1 where a1.a<6 and a1.b< 'zz'
|
|
union
|
|
select * from b1 where b1.b > 'auu')
|
|
select * from c1;
|
|
ERROR HY000: Unacceptable mutual recursion with anchored table 'a1'
|
|
drop table t1;
|
|
# WITH RECURSIVE vs just WITH
|
|
create table t1 (a int);
|
|
insert into t1 values
|
|
(0), (1), (2), (3), (4);
|
|
create table t2 (a int);
|
|
insert into t2 values
|
|
(1), (2), (3), (4), (5);
|
|
# just WITH : s refers to t defined after s
|
|
with
|
|
s(a) as (select t.a + 10 from t),
|
|
t(a) as (select t1.a from t1)
|
|
select * from s;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
# WITH RECURSIVE: s refers to t defined after s
|
|
with recursive
|
|
s(a) as (select t.a + 10 from t),
|
|
t(a) as (select t1.a from t1)
|
|
select * from s;
|
|
a
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
# just WITH : defined t1 is non-recursive and uses base tables t1,t2
|
|
with
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
3
|
|
1
|
|
2
|
|
4
|
|
5
|
|
explain
|
|
with
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 30
|
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
|
|
3 UNION t1 ALL NULL NULL NULL NULL 5
|
|
3 UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
|
#WITH RECURSIVE : defined t1 is recursive and uses only base table t2
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
3
|
|
4
|
|
5
|
|
explain
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
|
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 5
|
|
3 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
|
# just WITH : types of t1 columns are determined by all parts of union
|
|
create view v1 as
|
|
with
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a+1 from t1,t2 where t1.a=t2.a
|
|
)
|
|
select * from t1;
|
|
show columns from v1;
|
|
Field Type Null Key Default Extra
|
|
a bigint(20) YES NULL
|
|
# WITH RECURSIVE : types of t1 columns are determined by anchor parts
|
|
create view v2 as
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a+1 from t1,t2 where t1.a=t2.a
|
|
)
|
|
select * from t1;
|
|
show columns from v2;
|
|
Field Type Null Key Default Extra
|
|
a int(11) YES NULL
|
|
drop view v1,v2;
|
|
drop table t1,t2;
|
|
create table folks(id int, name char(32), dob date, father int, mother int);
|
|
insert into folks values
|
|
(100, 'Me', '2000-01-01', 20, 30),
|
|
(20, 'Dad', '1970-02-02', 10, 9),
|
|
(30, 'Mom', '1975-03-03', 8, 7),
|
|
(10, 'Grandpa Bill', '1940-04-05', null, null),
|
|
(9, 'Grandma Ann', '1941-10-15', null, null),
|
|
(25, 'Uncle Jim', '1968-11-18', 8, 7),
|
|
(98, 'Sister Amy', '2001-06-20', 20, 30),
|
|
(7, 'Grandma Sally', '1943-08-23', null, 6),
|
|
(8, 'Grandpa Ben', '1940-10-21', null, null),
|
|
(6, 'Grandgrandma Martha', '1923-05-17', null, null),
|
|
(67, 'Cousin Eddie', '1992-02-28', 25, 27),
|
|
(27, 'Auntie Melinda', '1971-03-29', null, null);
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the last select in the specification
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select p.*
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Cousin Eddie'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
67 Cousin Eddie 1992-02-28 25 27
|
|
25 Uncle Jim 1968-11-18 8 7
|
|
27 Auntie Melinda 1971-03-29 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# simple recursion with or in anchor and or in recursive part
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' or name='Sister Amy'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
98 Sister Amy 2001-06-20 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# two recursive definition, one uses another
|
|
with recursive
|
|
prev_gen
|
|
as
|
|
(
|
|
select folks.*
|
|
from folks, prev_gen
|
|
where folks.id=prev_gen.father or folks.id=prev_gen.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
union
|
|
select *
|
|
from ancestors
|
|
union
|
|
select *
|
|
from prev_gen
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
name dob
|
|
Me 2000-01-01
|
|
Dad 1970-02-02
|
|
Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05
|
|
Grandma Ann 1941-10-15
|
|
Grandma Sally 1943-08-23
|
|
Grandpa Ben 1940-10-21
|
|
Grandgrandma Martha 1923-05-17
|
|
# recursive definition with two attached non-recursive
|
|
with recursive
|
|
ancestors(id,name,dob)
|
|
as
|
|
(
|
|
with
|
|
father(child_id,id,name,dob)
|
|
as
|
|
(
|
|
select folks.id, f.id, f.name, f.dob
|
|
from folks, folks f
|
|
where folks.father=f.id
|
|
),
|
|
mother(child_id,id,name,dob)
|
|
as
|
|
(
|
|
select folks.id, m.id, m.name, m.dob
|
|
from folks, folks m
|
|
where folks.mother=m.id
|
|
)
|
|
select folks.id, folks.name, folks.dob
|
|
from folks
|
|
where name='Me'
|
|
union
|
|
select f.id, f.name, f.dob
|
|
from ancestors a, father f
|
|
where f.child_id=a.id
|
|
union
|
|
select m.id, m.name, m.dob
|
|
from ancestors a, mother m
|
|
where m.child_id=a.id
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
name dob
|
|
Me 2000-01-01
|
|
Dad 1970-02-02
|
|
Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05
|
|
Grandpa Ben 1940-10-21
|
|
Grandma Ann 1941-10-15
|
|
Grandma Sally 1943-08-23
|
|
Grandgrandma Martha 1923-05-17
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
descendants
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Grandpa Bill'
|
|
union
|
|
select folks.*
|
|
from folks, descendants as d
|
|
where d.id=folks.father or d.id=folks.mother
|
|
)
|
|
select * from descendants;
|
|
id name dob father mother
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
20 Dad 1970-02-02 10 9
|
|
100 Me 2000-01-01 20 30
|
|
98 Sister Amy 2001-06-20 20 30
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
descendants
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Grandma Sally'
|
|
union
|
|
select folks.*
|
|
from folks, descendants as d
|
|
where d.id=folks.father or d.id=folks.mother
|
|
)
|
|
select * from descendants;
|
|
id name dob father mother
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
30 Mom 1975-03-03 8 7
|
|
25 Uncle Jim 1968-11-18 8 7
|
|
100 Me 2000-01-01 20 30
|
|
98 Sister Amy 2001-06-20 20 30
|
|
67 Cousin Eddie 1992-02-28 25 27
|
|
# simple recursive table used three times in the main query
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father OR p.id = a.mother
|
|
)
|
|
select *
|
|
from ancestors t1, ancestors t2
|
|
where exists (select * from ancestors a
|
|
where a.father=t1.id AND a.mother=t2.id);
|
|
id name dob father mother id name dob father mother
|
|
20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6
|
|
# simple recursive table used three times in the main query
|
|
with
|
|
ancestor_couples(husband, h_dob, wife, w_dob)
|
|
as
|
|
(
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father OR p.id = a.mother
|
|
)
|
|
select t1.name, t1.dob, t2.name, t2.dob
|
|
from ancestors t1, ancestors t2
|
|
where exists (select * from ancestors a
|
|
where a.father=t1.id AND a.mother=t2.id)
|
|
)
|
|
select * from ancestor_couples;
|
|
husband h_dob wife w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# simple recursion with two selects in recursive part
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# mutual recursion with renaming
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with union all
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union all
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with renaming
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with union all
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union all
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with one select in the first definition
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select *
|
|
from ancestor_couple_ids;
|
|
h_id w_id
|
|
20 30
|
|
10 9
|
|
8 7
|
|
# join of a mutually recursive table with base tables
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, folks h, folks w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
name dob name dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# join of two mutually recursive tables
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
name dob name dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
explain extended
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
1 PRIMARY <derived3> ref key0 key0 5 c.h_id 2 100.00
|
|
1 PRIMARY <derived3> ref key0 key0 5 c.w_id 2 100.00
|
|
3 SUBQUERY folks ALL NULL NULL NULL NULL 12 100.00 Using where
|
|
4 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00
|
|
4 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
|
|
5 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00
|
|
5 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union3,4,5> ALL NULL NULL NULL NULL NULL NULL
|
|
2 UNCACHEABLE SUBQUERY <derived3> ALL NULL NULL NULL NULL 12 100.00 Using where
|
|
Warnings:
|
|
Note 1003 with recursive ancestor_couple_ids as (select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where ((`a`.`father` is not null) and (`a`.`mother` is not null)))coupled_ancestors as (select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where (`test`.`folks`.`name` = 'Me') union all select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where (`test`.`p`.`id` = `fa`.`h_id`) union all select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `ma` where (`test`.`p`.`id` = `ma`.`w_id`)), select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where ((`h`.`id` = `c`.`h_id`) and (`w`.`id` = `c`.`w_id`))
|
|
# simple mutual recursion
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select *
|
|
from ancestor_couple_ids;
|
|
h_id w_id
|
|
20 30
|
|
10 9
|
|
8 7
|
|
NULL NULL
|
|
NULL NULL
|
|
NULL NULL
|
|
NULL 6
|
|
NULL NULL
|
|
# join of two mutually recursive tables
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
name dob name dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# execution of prepared query using a recursive table
|
|
prepare stmt1 from "
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
";
|
|
execute stmt1;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
execute stmt1;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
deallocate prepare stmt1;
|
|
# view using a recursive table
|
|
create view v1 as
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
show create view v1;
|
|
View Create View character_set_client collation_connection
|
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with recursive ancestors as (select `folks`.`id` AS `id`,`folks`.`name` AS `name`,`folks`.`dob` AS `dob`,`folks`.`father` AS `father`,`folks`.`mother` AS `mother` from `folks` where ((`folks`.`name` = 'Me') and (`folks`.`dob` = '2000-01-01')) union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `a`) where ((`p`.`id` = `a`.`father`) or (`p`.`id` = `a`.`mother`)))select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors` latin1 latin1_swedish_ci
|
|
select * from v1;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
create view v2 as
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
show create view v2;
|
|
View Create View character_set_client collation_connection
|
|
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS with recursive ancestors as (select `folks`.`id` AS `id`,`folks`.`name` AS `name`,`folks`.`dob` AS `dob`,`folks`.`father` AS `father`,`folks`.`mother` AS `mother` from `folks` where (`folks`.`name` = 'Me') union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `fa`) where (`p`.`id` = `fa`.`father`) union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `ma`) where (`p`.`id` = `ma`.`mother`))select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors` latin1 latin1_swedish_ci
|
|
select * from v2;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop view v1,v2;
|
|
explain extended
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
|
|
2 SUBQUERY folks ALL NULL NULL NULL NULL 12 100.00 Using where
|
|
3 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with recursive ancestors as (select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where ((`test`.`folks`.`name` = 'Me') and (`test`.`folks`.`dob` = DATE'2000-01-01')) union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestors` `a` where ((`a`.`father` = `p`.`id`) or (`a`.`mother` = `p`.`id`)))select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors`
|
|
# recursive spec with two anchor selects and two recursive ones
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select p.* from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# recursive spec using union all
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union all
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me' and father is not null
|
|
union all
|
|
select mother, 1 from folks where name = 'Me' and mother is not null
|
|
union all
|
|
select father, fa.generation+1 from folks, ancestor_ids fa
|
|
where folks.id = fa.id and (father not in (select id from ancestor_ids))
|
|
union all
|
|
select mother, ma.generation+1 from folks, ancestor_ids ma
|
|
where folks.id = ma.id and (mother not in (select id from ancestor_ids))
|
|
)
|
|
select generation, name from ancestor_ids a, folks
|
|
where a.id = folks.id;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids'
|
|
set standards_compliant_cte=0;
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me' and father is not null
|
|
union all
|
|
select mother from folks where name = 'Me' and mother is not null
|
|
union all
|
|
select father, fa.generation+1 from folks, ancestor_ids fa
|
|
where folks.id = fa.id and (father not in (select id from ancestor_ids))
|
|
union all
|
|
select mother, ma.generation+1 from folks, ancestor_ids ma
|
|
where folks.id = ma.id and (mother not in (select id from ancestor_ids))
|
|
)
|
|
select generation, name from ancestor_ids a, folks
|
|
where a.id = folks.id;
|
|
ERROR HY000: WITH column list and SELECT field list have different column counts
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me' and father is not null
|
|
union all
|
|
select mother, 1 from folks where name = 'Me' and mother is not null
|
|
union all
|
|
select father, fa.generation+1 from folks, ancestor_ids fa
|
|
where folks.id = fa.id and father is not null and
|
|
(father not in (select id from ancestor_ids))
|
|
union all
|
|
select mother, ma.generation+1 from folks, ancestor_ids ma
|
|
where folks.id = ma.id and mother is not null and
|
|
(mother not in (select id from ancestor_ids))
|
|
)
|
|
select generation, name from ancestor_ids a, folks
|
|
where a.id = folks.id;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
2 Grandma Sally
|
|
2 Grandpa Ben
|
|
3 Grandgrandma Martha
|
|
set standards_compliant_cte=1;
|
|
with recursive
|
|
coupled_ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me' and father is not null
|
|
union
|
|
select mother from folks where name = 'Me' and mother is not null
|
|
union
|
|
select n.father
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
union
|
|
select n.mother
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
)
|
|
select p.* from coupled_ancestor_ids a, folks p
|
|
where a.id = p.id;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'coupled_ancestor_ids'
|
|
set statement standards_compliant_cte=0 for
|
|
with recursive
|
|
coupled_ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me' and father is not null
|
|
union
|
|
select mother from folks where name = 'Me' and mother is not null
|
|
union
|
|
select n.father
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
union
|
|
select n.mother
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
)
|
|
select p.* from coupled_ancestor_ids a, folks p
|
|
where a.id = p.id;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks left join ancestor_ids a on folks.id = a.id
|
|
union
|
|
select mother from folks left join ancestor_ids a on folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select p.* from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids'
|
|
set statement standards_compliant_cte=0 for
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks left join ancestor_ids a on folks.id = a.id
|
|
union
|
|
select mother from folks left join ancestor_ids a on folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select p.* from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
25 Uncle Jim 1968-11-18 8 7
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
27 Auntie Melinda 1971-03-29 NULL NULL
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select father, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
union
|
|
select mother, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
2 Grandma Sally
|
|
2 Grandpa Ben
|
|
3 Grandgrandma Martha
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select max(father), max(a.generation)+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
union
|
|
select max(mother), max(a.generation)+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids'
|
|
set statement standards_compliant_cte=0 for
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select max(father), a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
union
|
|
select max(mother), a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
set statement max_recursive_iterations=1 for
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select father, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
union
|
|
select mother, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
2 Grandma Sally
|
|
2 Grandpa Ben
|
|
# query with recursive tables using key access
|
|
alter table folks add primary key (id);
|
|
explain
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12
|
|
2 SUBQUERY folks ALL NULL NULL NULL NULL 12 Using where
|
|
3 RECURSIVE UNION p ALL PRIMARY NULL NULL NULL 12
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.p.id 2
|
|
4 RECURSIVE UNION p ALL PRIMARY NULL NULL NULL 12
|
|
4 RECURSIVE UNION <derived2> ref key0 key0 5 test.p.id 2
|
|
NULL UNION RESULT <union2,3,4> ALL NULL NULL NULL NULL NULL
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
#
|
|
# EXPLAIN FORMAT=JSON on a query where one recursive CTE uses another:
|
|
#
|
|
explain
|
|
with recursive
|
|
prev_gen
|
|
as
|
|
(
|
|
select folks.*
|
|
from folks, prev_gen
|
|
where folks.id=prev_gen.father or folks.id=prev_gen.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
union
|
|
select *
|
|
from ancestors
|
|
union
|
|
select *
|
|
from prev_gen
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 24
|
|
4 SUBQUERY folks ALL NULL NULL NULL NULL 12 Using where
|
|
6 RECURSIVE UNION <derived3> ALL NULL NULL NULL NULL 12
|
|
5 RECURSIVE UNION <derived4> ALL NULL NULL NULL NULL 24
|
|
NULL UNION RESULT <union4,6,5> ALL NULL NULL NULL NULL NULL
|
|
3 SUBQUERY folks ALL NULL NULL NULL NULL 12 Using where
|
|
2 RECURSIVE UNION folks ALL PRIMARY NULL NULL NULL 12
|
|
2 RECURSIVE UNION <derived3> ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union3,2> ALL NULL NULL NULL NULL NULL
|
|
explain FORMAT=JSON
|
|
with recursive
|
|
prev_gen
|
|
as
|
|
(
|
|
select folks.*
|
|
from folks, prev_gen
|
|
where folks.id=prev_gen.father or folks.id=prev_gen.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name='Me2'
|
|
union
|
|
select *
|
|
from ancestors where id < 234
|
|
union
|
|
select *
|
|
from prev_gen where id < 345
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"rows": 24,
|
|
"filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union4,6,5>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 4,
|
|
"table": {
|
|
"table_name": "folks",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "(folks.`name` = 'Me2')"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 6,
|
|
"table": {
|
|
"table_name": "<derived3>",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "(prev_gen.`id` < 345)",
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union3,2>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"table": {
|
|
"table_name": "folks",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "(folks.`name` = 'Me')"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"table": {
|
|
"table_name": "folks",
|
|
"access_type": "ALL",
|
|
"possible_keys": ["PRIMARY"],
|
|
"rows": 12,
|
|
"filtered": 100
|
|
},
|
|
"block-nl-join": {
|
|
"table": {
|
|
"table_name": "<derived3>",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100
|
|
},
|
|
"buffer_type": "flat",
|
|
"buffer_size": "256Kb",
|
|
"join_type": "BNL",
|
|
"attached_condition": "((prev_gen.father = folks.`id`) or (prev_gen.mother = folks.`id`))"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 5,
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"rows": 24,
|
|
"filtered": 100,
|
|
"attached_condition": "(ancestors.`id` < 234)"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#
|
|
explain format=json
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union all
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"table_name": "<derived3>",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union3,2>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"table": {
|
|
"table_name": "v",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "((v.`name` = 'Me') and (v.father is not null) and (v.mother is not null))"
|
|
},
|
|
"table": {
|
|
"table_name": "h",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["test.v.father"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
},
|
|
"table": {
|
|
"table_name": "w",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["test.v.mother"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"rows": 2,
|
|
"filtered": 100,
|
|
"attached_condition": "((a.father is not null) and (a.mother is not null))"
|
|
},
|
|
"table": {
|
|
"table_name": "h",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["a.father"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
},
|
|
"table": {
|
|
"table_name": "w",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["a.mother"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
create table my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
delete from my_ancestors;
|
|
insert into my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop table my_ancestors;
|
|
#
|
|
# MDEV-10883: execution of prepared statement from SELECT
|
|
# with recursive CTE that renames columns
|
|
#
|
|
prepare stmt from"
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
";
|
|
execute stmt;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
deallocate prepare stmt;
|
|
#
|
|
# MDEV-10881: execution of prepared statement from
|
|
# CREATE ... SELECT, INSERT ... SELECT
|
|
#
|
|
prepare stmt from"
|
|
create table my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
";
|
|
execute stmt;
|
|
deallocate prepare stmt;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
delete from my_ancestors;
|
|
prepare stmt from"
|
|
insert into my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
";
|
|
execute stmt;
|
|
deallocate prepare stmt;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop table my_ancestors;
|
|
#
|
|
# MDEV-10933: WITH clause together with SELECT in parenthesis
|
|
# CREATE SELECT
|
|
#
|
|
create table my_ancestors
|
|
(
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id
|
|
);
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop table my_ancestors;
|
|
drop table folks;
|
|
#
|
|
# MDEV-10372: [bb-10.2-mdev9864 tree] EXPLAIN with recursive CTE enters endless recursion
|
|
#
|
|
create table t1(a int);
|
|
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
explain format=json
|
|
with recursive t as (select a from t1 union select a+10 from t where a < 1000)
|
|
select * from t;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union2,3>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100,
|
|
"attached_condition": "(t.a < 1000)"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
drop table t1;
|
|
#
|
|
# MDEV-10737: recursive union with several anchors at the end
|
|
#
|
|
WITH RECURSIVE cte(n) AS
|
|
( SELECT n+1 FROM cte WHERE n < 5 UNION SELECT 1 UNION SELECT 1 )
|
|
SELECT * FROM cte;
|
|
n
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
#
|
|
# MDEV-10736: recursive definition with anchor over a table with blob
|
|
#
|
|
CREATE TABLE t1 (f VARCHAR(1024));
|
|
WITH RECURSIVE cte(f) AS
|
|
(SELECT t1.f FROM t1 UNION ALL SELECT cte.f FROM cte)
|
|
SELECT * FROM cte as t;
|
|
f
|
|
DROP TABLE t1;
|
|
#
|
|
# MDEV-10899: mergeable derived in the spec of recursive CTE
|
|
#
|
|
create table t1 (a int);
|
|
insert into t1 values
|
|
(0), (1), (2), (3), (4);
|
|
create table t2 (a int);
|
|
insert into t2 values
|
|
(1), (2), (3), (4), (5);
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select x.a from (select a from t2 where t2.a=3) x
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
3
|
|
4
|
|
5
|
|
explain
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select x.a from (select a from t2 where t2.a=3) x
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
|
|
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
|
|
4 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 5
|
|
4 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-11278: non-mergeable view in the spec of recursive CTE
|
|
#
|
|
create table t1 (a int);
|
|
insert into t1 values
|
|
(0), (1), (2), (3), (4);
|
|
create table t2 (a int);
|
|
insert into t2 values
|
|
(1), (2), (3), (4), (5);
|
|
create view v1 as
|
|
select a from t2 where a < 3
|
|
union
|
|
select a from t2 where a > 4;
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from v1 where a=1
|
|
union
|
|
select v1.a from t1,v1 where t1.a+1=v1.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
1
|
|
2
|
|
drop view v1;
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-11259: recursive CTE with concatenation operation
|
|
#
|
|
DROP TABLE IF EXISTS edges;
|
|
Warnings:
|
|
Note 1051 Unknown table 'test.edges'
|
|
CREATE TABLE edges(
|
|
a int(10) unsigned NOT NULL,
|
|
b int(10) unsigned NOT NULL,
|
|
PRIMARY KEY (a,b),
|
|
KEY b(b)
|
|
);
|
|
INSERT INTO edges
|
|
VALUES (1,3),(2,1),(2,4),(3,4),(3,5),(3,6),(4,7),(5,1),(5,6),(6,1);
|
|
DROP TABLE IF EXISTS edges2;
|
|
Warnings:
|
|
Note 1051 Unknown table 'test.edges2'
|
|
CREATE VIEW edges2 (a, b) AS
|
|
SELECT a, b FROM edges UNION ALL SELECT b, a FROM edges;
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges AS e
|
|
JOIN transitive_closure AS tc
|
|
ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT * FROM transitive_closure
|
|
ORDER BY a, b, distance;
|
|
a b distance path_string
|
|
1 3 1 1.3.
|
|
1 4 2 1.3.4.
|
|
1 5 2 1.3.5.
|
|
1 6 2 1.3.6.
|
|
1 6 3 1.3.5.6.
|
|
1 7 3 1.3.4.7.
|
|
2 1 1 2.1.
|
|
2 3 2 2.1.3.
|
|
2 4 1 2.4.
|
|
2 4 3 2.1.3.4.
|
|
2 5 3 2.1.3.5.
|
|
2 6 3 2.1.3.6.
|
|
2 6 4 2.1.3.5.6.
|
|
2 7 2 2.4.7.
|
|
2 7 4 2.1.3.4.7.
|
|
3 1 2 3.5.1.
|
|
3 1 2 3.6.1.
|
|
3 1 3 3.5.6.1.
|
|
3 4 1 3.4.
|
|
3 5 1 3.5.
|
|
3 6 1 3.6.
|
|
3 6 2 3.5.6.
|
|
3 7 2 3.4.7.
|
|
4 7 1 4.7.
|
|
5 1 1 5.1.
|
|
5 1 2 5.6.1.
|
|
5 3 2 5.1.3.
|
|
5 3 3 5.6.1.3.
|
|
5 4 3 5.1.3.4.
|
|
5 4 4 5.6.1.3.4.
|
|
5 6 1 5.6.
|
|
5 6 3 5.1.3.6.
|
|
5 7 4 5.1.3.4.7.
|
|
5 7 5 5.6.1.3.4.7.
|
|
6 1 1 6.1.
|
|
6 3 2 6.1.3.
|
|
6 4 3 6.1.3.4.
|
|
6 5 3 6.1.3.5.
|
|
6 7 4 6.1.3.4.7.
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges
|
|
WHERE a = 1 -- source
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges AS e
|
|
JOIN transitive_closure AS tc ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT * FROM transitive_closure
|
|
WHERE b = 6 -- destination
|
|
ORDER BY a, b, distance;
|
|
a b distance path_string
|
|
1 6 2 1.3.6.
|
|
1 6 3 1.3.5.6.
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges2
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges2 AS e
|
|
JOIN transitive_closure AS tc ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT * FROM transitive_closure
|
|
ORDER BY a, b, distance;
|
|
a b distance path_string
|
|
1 2 1 1.2.
|
|
1 2 3 1.3.4.2.
|
|
1 2 4 1.5.3.4.2.
|
|
1 2 4 1.6.3.4.2.
|
|
1 2 5 1.5.6.3.4.2.
|
|
1 2 5 1.6.5.3.4.2.
|
|
1 3 1 1.3.
|
|
1 3 2 1.5.3.
|
|
1 3 2 1.6.3.
|
|
1 3 3 1.2.4.3.
|
|
1 3 3 1.5.6.3.
|
|
1 3 3 1.6.5.3.
|
|
1 4 2 1.2.4.
|
|
1 4 2 1.3.4.
|
|
1 4 3 1.5.3.4.
|
|
1 4 3 1.6.3.4.
|
|
1 4 4 1.5.6.3.4.
|
|
1 4 4 1.6.5.3.4.
|
|
1 5 1 1.5.
|
|
1 5 2 1.3.5.
|
|
1 5 2 1.6.5.
|
|
1 5 3 1.3.6.5.
|
|
1 5 3 1.6.3.5.
|
|
1 5 4 1.2.4.3.5.
|
|
1 5 5 1.2.4.3.6.5.
|
|
1 6 1 1.6.
|
|
1 6 2 1.3.6.
|
|
1 6 2 1.5.6.
|
|
1 6 3 1.3.5.6.
|
|
1 6 3 1.5.3.6.
|
|
1 6 4 1.2.4.3.6.
|
|
1 6 5 1.2.4.3.5.6.
|
|
1 7 3 1.2.4.7.
|
|
1 7 3 1.3.4.7.
|
|
1 7 4 1.5.3.4.7.
|
|
1 7 4 1.6.3.4.7.
|
|
1 7 5 1.5.6.3.4.7.
|
|
1 7 5 1.6.5.3.4.7.
|
|
2 1 1 2.1.
|
|
2 1 3 2.4.3.1.
|
|
2 1 4 2.4.3.5.1.
|
|
2 1 4 2.4.3.6.1.
|
|
2 1 5 2.4.3.5.6.1.
|
|
2 1 5 2.4.3.6.5.1.
|
|
2 3 2 2.1.3.
|
|
2 3 2 2.4.3.
|
|
2 3 3 2.1.5.3.
|
|
2 3 3 2.1.6.3.
|
|
2 3 4 2.1.5.6.3.
|
|
2 3 4 2.1.6.5.3.
|
|
2 4 1 2.4.
|
|
2 4 3 2.1.3.4.
|
|
2 4 4 2.1.5.3.4.
|
|
2 4 4 2.1.6.3.4.
|
|
2 4 5 2.1.5.6.3.4.
|
|
2 4 5 2.1.6.5.3.4.
|
|
2 5 2 2.1.5.
|
|
2 5 3 2.1.3.5.
|
|
2 5 3 2.1.6.5.
|
|
2 5 3 2.4.3.5.
|
|
2 5 4 2.1.3.6.5.
|
|
2 5 4 2.1.6.3.5.
|
|
2 5 4 2.4.3.1.5.
|
|
2 5 4 2.4.3.6.5.
|
|
2 5 5 2.4.3.1.6.5.
|
|
2 5 5 2.4.3.6.1.5.
|
|
2 6 2 2.1.6.
|
|
2 6 3 2.1.3.6.
|
|
2 6 3 2.1.5.6.
|
|
2 6 3 2.4.3.6.
|
|
2 6 4 2.1.3.5.6.
|
|
2 6 4 2.1.5.3.6.
|
|
2 6 4 2.4.3.1.6.
|
|
2 6 4 2.4.3.5.6.
|
|
2 6 5 2.4.3.1.5.6.
|
|
2 6 5 2.4.3.5.1.6.
|
|
2 7 2 2.4.7.
|
|
2 7 4 2.1.3.4.7.
|
|
2 7 5 2.1.5.3.4.7.
|
|
2 7 5 2.1.6.3.4.7.
|
|
2 7 6 2.1.5.6.3.4.7.
|
|
2 7 6 2.1.6.5.3.4.7.
|
|
3 1 1 3.1.
|
|
3 1 2 3.5.1.
|
|
3 1 2 3.6.1.
|
|
3 1 3 3.4.2.1.
|
|
3 1 3 3.5.6.1.
|
|
3 1 3 3.6.5.1.
|
|
3 2 2 3.1.2.
|
|
3 2 2 3.4.2.
|
|
3 2 3 3.5.1.2.
|
|
3 2 3 3.6.1.2.
|
|
3 2 4 3.5.6.1.2.
|
|
3 2 4 3.6.5.1.2.
|
|
3 4 1 3.4.
|
|
3 4 3 3.1.2.4.
|
|
3 4 4 3.5.1.2.4.
|
|
3 4 4 3.6.1.2.4.
|
|
3 4 5 3.5.6.1.2.4.
|
|
3 4 5 3.6.5.1.2.4.
|
|
3 5 1 3.5.
|
|
3 5 2 3.1.5.
|
|
3 5 2 3.6.5.
|
|
3 5 3 3.1.6.5.
|
|
3 5 3 3.6.1.5.
|
|
3 5 4 3.4.2.1.5.
|
|
3 5 5 3.4.2.1.6.5.
|
|
3 6 1 3.6.
|
|
3 6 2 3.1.6.
|
|
3 6 2 3.5.6.
|
|
3 6 3 3.1.5.6.
|
|
3 6 3 3.5.1.6.
|
|
3 6 4 3.4.2.1.6.
|
|
3 6 5 3.4.2.1.5.6.
|
|
3 7 2 3.4.7.
|
|
3 7 4 3.1.2.4.7.
|
|
3 7 5 3.5.1.2.4.7.
|
|
3 7 5 3.6.1.2.4.7.
|
|
3 7 6 3.5.6.1.2.4.7.
|
|
3 7 6 3.6.5.1.2.4.7.
|
|
4 1 2 4.2.1.
|
|
4 1 2 4.3.1.
|
|
4 1 3 4.3.5.1.
|
|
4 1 3 4.3.6.1.
|
|
4 1 4 4.3.5.6.1.
|
|
4 1 4 4.3.6.5.1.
|
|
4 2 1 4.2.
|
|
4 2 3 4.3.1.2.
|
|
4 2 4 4.3.5.1.2.
|
|
4 2 4 4.3.6.1.2.
|
|
4 2 5 4.3.5.6.1.2.
|
|
4 2 5 4.3.6.5.1.2.
|
|
4 3 1 4.3.
|
|
4 3 3 4.2.1.3.
|
|
4 3 4 4.2.1.5.3.
|
|
4 3 4 4.2.1.6.3.
|
|
4 3 5 4.2.1.5.6.3.
|
|
4 3 5 4.2.1.6.5.3.
|
|
4 5 2 4.3.5.
|
|
4 5 3 4.2.1.5.
|
|
4 5 3 4.3.1.5.
|
|
4 5 3 4.3.6.5.
|
|
4 5 4 4.2.1.3.5.
|
|
4 5 4 4.2.1.6.5.
|
|
4 5 4 4.3.1.6.5.
|
|
4 5 4 4.3.6.1.5.
|
|
4 5 5 4.2.1.3.6.5.
|
|
4 5 5 4.2.1.6.3.5.
|
|
4 6 2 4.3.6.
|
|
4 6 3 4.2.1.6.
|
|
4 6 3 4.3.1.6.
|
|
4 6 3 4.3.5.6.
|
|
4 6 4 4.2.1.3.6.
|
|
4 6 4 4.2.1.5.6.
|
|
4 6 4 4.3.1.5.6.
|
|
4 6 4 4.3.5.1.6.
|
|
4 6 5 4.2.1.3.5.6.
|
|
4 6 5 4.2.1.5.3.6.
|
|
4 7 1 4.7.
|
|
5 1 1 5.1.
|
|
5 1 2 5.3.1.
|
|
5 1 2 5.6.1.
|
|
5 1 3 5.3.6.1.
|
|
5 1 3 5.6.3.1.
|
|
5 1 4 5.3.4.2.1.
|
|
5 1 5 5.6.3.4.2.1.
|
|
5 2 2 5.1.2.
|
|
5 2 3 5.3.1.2.
|
|
5 2 3 5.3.4.2.
|
|
5 2 3 5.6.1.2.
|
|
5 2 4 5.1.3.4.2.
|
|
5 2 4 5.3.6.1.2.
|
|
5 2 4 5.6.3.1.2.
|
|
5 2 4 5.6.3.4.2.
|
|
5 2 5 5.1.6.3.4.2.
|
|
5 2 5 5.6.1.3.4.2.
|
|
5 3 1 5.3.
|
|
5 3 2 5.1.3.
|
|
5 3 2 5.6.3.
|
|
5 3 3 5.1.6.3.
|
|
5 3 3 5.6.1.3.
|
|
5 3 4 5.1.2.4.3.
|
|
5 3 5 5.6.1.2.4.3.
|
|
5 4 2 5.3.4.
|
|
5 4 3 5.1.2.4.
|
|
5 4 3 5.1.3.4.
|
|
5 4 3 5.6.3.4.
|
|
5 4 4 5.1.6.3.4.
|
|
5 4 4 5.3.1.2.4.
|
|
5 4 4 5.6.1.2.4.
|
|
5 4 4 5.6.1.3.4.
|
|
5 4 5 5.3.6.1.2.4.
|
|
5 4 5 5.6.3.1.2.4.
|
|
5 6 1 5.6.
|
|
5 6 2 5.1.6.
|
|
5 6 2 5.3.6.
|
|
5 6 3 5.1.3.6.
|
|
5 6 3 5.3.1.6.
|
|
5 6 5 5.1.2.4.3.6.
|
|
5 6 5 5.3.4.2.1.6.
|
|
5 7 3 5.3.4.7.
|
|
5 7 4 5.1.2.4.7.
|
|
5 7 4 5.1.3.4.7.
|
|
5 7 4 5.6.3.4.7.
|
|
5 7 5 5.1.6.3.4.7.
|
|
5 7 5 5.3.1.2.4.7.
|
|
5 7 5 5.6.1.2.4.7.
|
|
5 7 5 5.6.1.3.4.7.
|
|
5 7 6 5.3.6.1.2.4.7.
|
|
5 7 6 5.6.3.1.2.4.7.
|
|
6 1 1 6.1.
|
|
6 1 2 6.3.1.
|
|
6 1 2 6.5.1.
|
|
6 1 3 6.3.5.1.
|
|
6 1 3 6.5.3.1.
|
|
6 1 4 6.3.4.2.1.
|
|
6 1 5 6.5.3.4.2.1.
|
|
6 2 2 6.1.2.
|
|
6 2 3 6.3.1.2.
|
|
6 2 3 6.3.4.2.
|
|
6 2 3 6.5.1.2.
|
|
6 2 4 6.1.3.4.2.
|
|
6 2 4 6.3.5.1.2.
|
|
6 2 4 6.5.3.1.2.
|
|
6 2 4 6.5.3.4.2.
|
|
6 2 5 6.1.5.3.4.2.
|
|
6 2 5 6.5.1.3.4.2.
|
|
6 3 1 6.3.
|
|
6 3 2 6.1.3.
|
|
6 3 2 6.5.3.
|
|
6 3 3 6.1.5.3.
|
|
6 3 3 6.5.1.3.
|
|
6 3 4 6.1.2.4.3.
|
|
6 3 5 6.5.1.2.4.3.
|
|
6 4 2 6.3.4.
|
|
6 4 3 6.1.2.4.
|
|
6 4 3 6.1.3.4.
|
|
6 4 3 6.5.3.4.
|
|
6 4 4 6.1.5.3.4.
|
|
6 4 4 6.3.1.2.4.
|
|
6 4 4 6.5.1.2.4.
|
|
6 4 4 6.5.1.3.4.
|
|
6 4 5 6.3.5.1.2.4.
|
|
6 4 5 6.5.3.1.2.4.
|
|
6 5 1 6.5.
|
|
6 5 2 6.1.5.
|
|
6 5 2 6.3.5.
|
|
6 5 3 6.1.3.5.
|
|
6 5 3 6.3.1.5.
|
|
6 5 5 6.1.2.4.3.5.
|
|
6 5 5 6.3.4.2.1.5.
|
|
6 7 3 6.3.4.7.
|
|
6 7 4 6.1.2.4.7.
|
|
6 7 4 6.1.3.4.7.
|
|
6 7 4 6.5.3.4.7.
|
|
6 7 5 6.1.5.3.4.7.
|
|
6 7 5 6.3.1.2.4.7.
|
|
6 7 5 6.5.1.2.4.7.
|
|
6 7 5 6.5.1.3.4.7.
|
|
6 7 6 6.3.5.1.2.4.7.
|
|
6 7 6 6.5.3.1.2.4.7.
|
|
7 1 3 7.4.2.1.
|
|
7 1 3 7.4.3.1.
|
|
7 1 4 7.4.3.5.1.
|
|
7 1 4 7.4.3.6.1.
|
|
7 1 5 7.4.3.5.6.1.
|
|
7 1 5 7.4.3.6.5.1.
|
|
7 2 2 7.4.2.
|
|
7 2 4 7.4.3.1.2.
|
|
7 2 5 7.4.3.5.1.2.
|
|
7 2 5 7.4.3.6.1.2.
|
|
7 2 6 7.4.3.5.6.1.2.
|
|
7 2 6 7.4.3.6.5.1.2.
|
|
7 3 2 7.4.3.
|
|
7 3 4 7.4.2.1.3.
|
|
7 3 5 7.4.2.1.5.3.
|
|
7 3 5 7.4.2.1.6.3.
|
|
7 3 6 7.4.2.1.5.6.3.
|
|
7 3 6 7.4.2.1.6.5.3.
|
|
7 4 1 7.4.
|
|
7 5 3 7.4.3.5.
|
|
7 5 4 7.4.2.1.5.
|
|
7 5 4 7.4.3.1.5.
|
|
7 5 4 7.4.3.6.5.
|
|
7 5 5 7.4.2.1.3.5.
|
|
7 5 5 7.4.2.1.6.5.
|
|
7 5 5 7.4.3.1.6.5.
|
|
7 5 5 7.4.3.6.1.5.
|
|
7 5 6 7.4.2.1.3.6.5.
|
|
7 5 6 7.4.2.1.6.3.5.
|
|
7 6 3 7.4.3.6.
|
|
7 6 4 7.4.2.1.6.
|
|
7 6 4 7.4.3.1.6.
|
|
7 6 4 7.4.3.5.6.
|
|
7 6 5 7.4.2.1.3.6.
|
|
7 6 5 7.4.2.1.5.6.
|
|
7 6 5 7.4.3.1.5.6.
|
|
7 6 5 7.4.3.5.1.6.
|
|
7 6 6 7.4.2.1.3.5.6.
|
|
7 6 6 7.4.2.1.5.3.6.
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string)
|
|
AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges2
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges2 AS e
|
|
JOIN transitive_closure AS tc ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT a, b, min(distance) AS dist FROM transitive_closure
|
|
GROUP BY a, b
|
|
ORDER BY a, dist, b;
|
|
a b dist
|
|
1 2 1
|
|
1 3 1
|
|
1 4 2
|
|
1 5 1
|
|
1 6 1
|
|
1 7 3
|
|
2 1 1
|
|
2 3 2
|
|
2 4 1
|
|
2 5 2
|
|
2 6 2
|
|
2 7 2
|
|
3 1 1
|
|
3 2 2
|
|
3 4 1
|
|
3 5 1
|
|
3 6 1
|
|
3 7 2
|
|
4 1 2
|
|
4 2 1
|
|
4 3 1
|
|
4 5 2
|
|
4 6 2
|
|
4 7 1
|
|
5 1 1
|
|
5 2 2
|
|
5 3 1
|
|
5 4 2
|
|
5 6 1
|
|
5 7 3
|
|
6 1 1
|
|
6 2 2
|
|
6 3 1
|
|
6 4 2
|
|
6 5 1
|
|
6 7 3
|
|
7 1 3
|
|
7 2 2
|
|
7 3 2
|
|
7 4 1
|
|
7 5 3
|
|
7 6 3
|
|
DROP VIEW edges2;
|
|
DROP TABLE edges;
|