Recursive CTE - Get descendants (many-to-many relationship)

删除回忆录丶 提交于 2020-01-11 11:21:52

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!