在具有所有父母的树中任何节点的mysql中获取完整的父/子关系树
Posted
技术标签:
【中文标题】在具有所有父母的树中任何节点的mysql中获取完整的父/子关系树【英文标题】:Get full tree of parent/child relationships in mysql of any node in the tree with all parents 【发布时间】:2020-05-17 23:50:46 【问题描述】:示例数据:
+----+-------+----------+
| org_id | Name | ParentID |
+----+-------+----------+
| 1 | Org1 | 2 |
| 2 | Org2 | NULL |
| 3 | Org3 | 5 |
| 5 | Org5 | 1 |
| 14 | Org14 | 1 |
+----+-------+----------+
如果我以 org_id 1 (Org1) 的用户身份登录。我想检索该用户的完整树。
我有以下递归查询:
WITH RECURSIVE cte (org_id, name, parent_id) AS (
SELECT org_id, name, parent_id
FROM organization
WHERE org_id = 1
UNION ALL
SELECT t1.org_id, t1.name, t1.parent_id
FROM organization t1
INNER JOIN cte t2 ON t1.parent_id = t2.org_id
)
SELECT * FROM cte;
但是,这个查询只给了我当前 id 的孩子(在这个例子中是 Org1)。我怎样才能在结果集中也包括所有的父母,这样我就可以准确地重建整个树?
编辑:我使用的是 MariaDB 版本 10.4.10
编辑: 我尝试了以下答案中的查询,但出现语法错误:
【问题讨论】:
是 mysql 还是 MariaDB?截至 2020 年,这是两种截然不同的动物。(还有什么版本?) 您的查询工作正常。问题一定出在其他地方。见db-fiddle.com/f/7QeMCpSyrrxQZwBLgn3KbS/0 【参考方案1】:您有一个 CTE 可以获取孩子。为什么不使用另一个去相反的方向并得到父母:
MySQL:
(WITH RECURSIVE cte (id, name, parent_id) AS (
SELECT id, name, parent_id
FROM organization
WHERE id = 1
UNION
SELECT t1.id, t1.name, t1.parent_id
FROM organization t1
INNER JOIN cte t2 ON t1.parent_id = t2.id
)
SELECT * FROM cte)
UNION
(WITH RECURSIVE cte (id, name, parent_id) AS (
SELECT id, name, parent_id
FROM organization
WHERE id = 1
UNION
SELECT t1.id, t1.name, t1.parent_id
FROM organization t1
INNER JOIN cte t2 ON t2.parent_id = t1.id
)
SELECT * FROM cte)
还有一个同时适用于 MySQL 和 MariaDB 的版本:
MySQL/MariaDB:
WITH RECURSIVE cte (id, name, parent_id, dir) AS (
SELECT id, name, parent_id, cast(null as char(10)) as dir
FROM organization
WHERE id = 1
UNION
SELECT t1.id, t1.name, t1.parent_id, ifnull(t2.dir, 'down')
FROM organization t1
INNER JOIN cte t2 ON t1.parent_id = t2.id and ifnull(t2.dir, 'down')='down'
UNION
SELECT t1.id, t1.name, t1.parent_id, ifnull(t2.dir, 'up')
FROM organization t1
INNER JOIN cte t2 ON t2.parent_id = t1.id and ifnull(t2.dir, 'up')='up'
)
SELECT id, name, parent_id FROM cte;
见db-fiddle和dbfiddle
【讨论】:
感谢您的回复!这似乎是解决此问题的正确方法,但我无法使其正常工作。我不断收到语法错误“(位置 1 的“WITH”附近)”。我只能在没有括号的情况下执行查询的第一部分(在 UNION 之前),但是如果添加了它们,它就不再起作用了 我编辑了我的原始帖子,我不断收到语法错误。 MariaDB 的语法不同吗? 我用 mariaDB 创建了一个数据库小提琴:dbfiddle.uk/… 看起来 MariaDB 不像 MySQL 那样喜欢 CTE 周围的括号。添加了 MariaDB 兼容版本。 原来需要将NULL转换为匹配的数据类型。虽然可以被认为是一个错误。现在可以在 MariaDB 和 MySQL 中使用。以上是关于在具有所有父母的树中任何节点的mysql中获取完整的父/子关系树的主要内容,如果未能解决你的问题,请参考以下文章