Reputation: 21
There is one problem that I encountered and that can we solved using recursive query but my code is giving error in MySQL.
Problem is as follow:
person supervisor
Mary Susan
David Mary
Bob Alice
Alice David
Find all supervisor(direct and indirect) of Bob?
Here is my solution for above question:
create recursive view find_all(person,supervisor,depth) as
(
select person,supervisor,0 as depth from employee as e
where e.person = 'Bob'
union all
select in1.person,out1.supervisor,in1.depth+1
from find_all as in1,employee as out1
and in1.supervisor = out1.person
and in1.depth<=100
);
And for output:
select * from find_all;
Upvotes: 0
Views: 444
Reputation: 4694
Here's one approach. Just create a normal view. The view contains the recursive WITH
clause.
CREATE VIEW find_all(person,supervisor,depth) AS
WITH RECURSIVE cte1 AS (
SELECT person, supervisor, 0 AS depth
FROM employee AS e
WHERE e.person = 'Bob'
UNION ALL
SELECT in1.person, out1.supervisor, in1.depth+1
FROM cte1 AS in1, employee AS out1
WHERE in1.supervisor = out1.person
AND in1.depth <= 100
)
SELECT * FROM cte1
;
Result:
select * from find_all;
+--------+------------+-------+
| person | supervisor | depth |
+--------+------------+-------+
| Bob | Alice | 0 |
| Bob | David | 1 |
| Bob | Mary | 2 |
| Bob | Susan | 3 |
+--------+------------+-------+
Alternate form:
The <from clause>
contains a <table reference list>
which is a comma separated list of <table reference>, <table reference>, ...
. This produces cross join
behavior. We then use a WHERE
clause to effectively inner join
these table references.
It's commonly suggested to use a single <table reference>
, for several good reasons, which can contain a <joined table>
. The second UNION
term below contains an example of a <joined table>
.
A couple of advantages are ease of identifying (and not accidentally forgetting) the corresponding <join condition>
and easier to change between join types.
CREATE VIEW find_all(person,supervisor,depth) AS
WITH RECURSIVE cte1 AS (
SELECT person, supervisor, 0 AS depth
FROM employee AS e
WHERE e.person = 'Bob'
UNION ALL
SELECT in1.person, out1.supervisor, in1.depth+1
FROM cte1 AS in1
JOIN employee AS out1
ON in1.supervisor = out1.person
WHERE in1.depth <= 100
)
SELECT * FROM cte1
;
In this case, the depth logic is not really part of the <join condition>
. It's really a subsequent filter of the rows produced by the join
.
The difference is seen when, for example, we have a left outer join
. We don't want that logic to just generate more nulls for the right table columns. We want that logic to produce no further rows when depth
is exceeded.
Upvotes: 1