问题
What I have:
Given a tree (or more like a directed graph) that describes how a system is composed by its generic parts. For now let this system be e.g. the human body and the nodes its body parts.
So for instance 3
could be the liver that has a left and a right lobe (6
and 9
), in both of which there are veins (8
) (that can also be found at any unspecified place of the liver, hence 8
->3
) but also in the tongue (5
). The lung (7
) - which is in the chest (4
) - also has a right lobe, and so on... (Well, of course there is no lung in the liver and also a 6
->7
would be reasonable so this example wasn't the best but you get it.)
So I have this data in a database like this:
table: part
+----+------------+ id is primary key
| id | name |
+----+------------+
| 1 | head |
| 2 | mouth |
| 3 | liver |
| 4 | chest |
| 5 | tongue |
| 6 | left lobe |
| 7 | lung |
| 8 | veins |
| 9 | right lobe |
+----+------------+
table: partpart
+-------+---------+ part&cont is primary key
| part | cont | part is foreign key for part.id
+-------+---------+ cont is foreign key for part.id
| 2 | 1 |
| 3 | 1 |
| 5 | 2 |
| 6 | 3 |
| 7 | 3 |
| 7 | 4 |
| 8 | 3 |
| 8 | 5 |
| 8 | 6 |
| 8 | 9 |
| 9 | 3 |
| 9 | 7 |
+-------+---------+
What I want to achieve:
I'd like to query all parts that can be found in part 3
and expecting a result like this one:
result of query
+-------+---------+
| part | subpart |
+-------+---------+
| 3 | 6 |
| 3 | 7 |
| 3 | 8 |
| 3 | 9 |
| 6 | 8 |
| 7 | 9 |
| 9 | 8 |
+-------+---------+
I have the feeling that getting the result in this desired format is not feasible, still it would be great to have it as a similar set because my purpose is to display the data for the user like that:
3
├─ 6
│ └─ 8
├─ 7
│ └─ 9
│ └─ 8
├─ 8
└─ 9
└─ 8
How I'm trying:
WITH RECURSIVE tree AS (
SELECT part.id as part, partpart.cont (..where to define subpart?)
FROM part JOIN partpart
ON part.id = partpart.part
WHERE part.id = 3
UNION ALL
SELECT part.id, partpart.cont
FROM (part JOIN partpart
ON part.id = partpart.part
), tree
WHERE partpart.cont = tree.part
)
SELECT part, subpart FROM tree
This is the closest I could do but of course it doesn't work.
回答1:
Problem solved, here is the query I needed, I hope it once helps someone else too...
WITH RECURSIVE graph AS (
SELECT
p.id AS subpart,
pp.cont AS part
FROM part p JOIN partpart pp
ON p.id = pp.part
WHERE pp.cont = 3
UNION ALL
SELECT
part.id,
partpart.cont
FROM (part JOIN partpart
ON part.id = partpart.part
), graph WHERE partpart.cont = graph.subpart
)
SELECT part, subpart, FROM graph
来源:https://stackoverflow.com/questions/47780183/recursive-cte-get-descendants-many-to-many-relationship