sql - 获取指定记录的顶级父级

时间:2018-06-18 11:18:11

标签: mysql sql

我有一个标准的嵌套类别树:

| 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

的父类别

2 个答案:

答案 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);