I am working with a hierarchy problem where the nodes have two parents and need get only the nodes where both parents are in the result.
In the happy world, this query would be perfect
WITH RECURSIVE granters (id, parents) AS (
SELECT id FROM `hierarchy` WHERE id in ("id1", "id2", "id6"....)
UNION ALL
SELECT h1.id, h1.parents FROM `hierarchy` h1
WHERE h1.parent2 in (SELECT id FROM granters)
AND h1.parent2 in (SELECT id FROM granters)
)
SELECT * FROM granters g
But mysql don’t allow use CTE as subquery, in multiples inner joins or in right join, so, I don’t know how filter it.
My best approach is this:
WITH RECURSIVE granters (id) AS (
SELECT id FROM `hierarchy` WHERE id in ("A", "B")
UNION ALL
SELECT h1.id FROM `hierarchy` h1 INNER JOIN granters g
ON h1.parent1 = g.id
OR h1.parent2 = g.id
)
SELECT * FROM hierarchy g
WHERE g.id IN ("A", "B")
OR (
g.parent1 IN (SELECT * FROM granters)
AND g.parent2 IN (SELECT * FROM granters)
)
But the problem is that first return all element with as least one parent and after filter all elements don’t have all parents… but if a grandfather is missing return the node anyway because both parents are in granters.
Data
id | parent1 | parent2 |
---|---|---|
A | A1 | A2 |
B | B1 | B2 |
C | A | B |
D | B | H |
E | C | D |
Actual output:
ID | parent1 | parent2 | notes |
---|---|---|---|
A | A1 | A2 | Good, is a selected value |
B | B1 | B2 | Good, is selected value |
C | A | B | Good, A and B are in result |
E | C | D | Bad, D is missing because H is missing |
Expected output:
ID | parent1 | parent2 |
---|---|---|
A | A1 | A2 |
B | B1 | B2 |
C | A | B |
-- Data
CREATE TABLE `hierarchy` (
`id` char(36) NOT NULL,
`parent1` char(36),
`parent2` char(36),
PRIMARY KEY (`id`)
);
INSERT INTO `hierarchy` (id,parent1,parent2) VALUES
('A','A1','A2'),
('B','B1','B2'),
('C','A','B'),
('D','B','H'),
('E','C','D');
2
Answers
fiddle (source data is expanded)
MySQL allow several join’s in recursive query, excluding the request itself.
We try replace
parent
byparent of parent
up to values in(‘A’,’B’),then we select the appropriate rows.
Example
Output is
With test data
Demo
Upd1. Perhaps, since we are not checking all the options, additional verification is needed. Need to think.