我有一个标准的嵌套类别树:
| id | parent_id | name |
+----+-----------+----------------+
| 1 | 0 | Category 1 |
| 2 | 0 | Category 2 |
| 3 | 0 | Category 3 |
| 4 | 1 | Category 1.1 |
| 5 | 1 | Category 1.2 |
| 6 | 2 | Category 2.1 |
| 7 | 2 | Category 2.2 |
| 8 | 7 | Category 2.2.1 |
现在我需要获得指定项目的顶级父级,所以我这样做:
SELECT
cat.*
FROM
categories cat
LEFT JOIN
categories subCat
ON
subCat.parent_id = cat.id
AND cat.parent_id = 0
WHERE
subCat.id = 5;
如果项目是第一级孩子,它工作正常,但项目是二级孩子(例如8
)我没有得到记录 - 怎么做?
这是SQlFiddle:http://sqlfiddle.com/#!9/5879bd/11
更新
这是一个真实的例子:http://sqlfiddle.com/#!9/6f1d1c/1
我想获得Xiaomi
答案 0 :(得分:1)
使用MySQL 5.6,您无法使用递归CTE。
要正确地执行此操作,对于任意树深度,您需要编写一个遍历层次结构并返回顶层节点的函数/过程。
作为一种变通方法,当设置了最大级别 d 时,您可以保持加入父级( d - 1)次。使用coalesce()
获取路径中的第一个非空值。所以在你的情况下,对于 d = 3:
SELECT c.*
FROM categories c
INNER JOIN (SELECT coalesce(c3.id, c2.id, c1.id) id
FROM categories c1
LEFT JOIN categories c2
ON c2.id = c1.parent_id
LEFT JOIN categories c3
ON c3.id = c2.parent_id
WHERE c1.id = 10) t
ON t.id = c.id;
(我首先选择顶部节点的ID,然后选择内部连接,以避免所有列上的coalesce()
。如果顶部节点中列的值为0,则可能会在可空列上产生错误结果null但不适用于任何子节点。它应显示NULL
,但会错误地显示子节点的非值。)
但请注意:如果深度增加,它将失败!
答案 1 :(得分:0)
这回答了问题的原始版本。
要获得最高级别,您可以使用name
列:
SELECT c.*
FROM categories c JOIN
categories sc
ON sc.id = 10 AND
c.name = SUBSTRING_INDEX(sc.name, '.', 1);