按外键中的递归量对MySQL查询结果排序

按外键中的递归量对MySQL查询结果排序,mysql,recursion,sql-order-by,hierarchical-data,Mysql,Recursion,Sql Order By,Hierarchical Data,我有下表: +----+--------+ | id | parent | +----+--------+ | 1 | 4 | | 2 | 1 | | 3 | NULL | | 4 | NULL | | 5 | 2 | | 6 | 3 | +----+--------+ 我希望这张桌子的顺序如下: +----+--------+------------------------------------------------------

我有下表:

+----+--------+
| id | parent |
+----+--------+
|  1 | 4      |
|  2 | 1      |
|  3 | NULL   |
|  4 | NULL   |
|  5 | 2      |
|  6 | 3      |
+----+--------+
我希望这张桌子的顺序如下:

+----+--------+------------------------------------------------------------+
| id | parent |             Why it has to be ordered like this             |
+----+--------+------------------------------------------------------------+
|  5 | 2      | 5 has parent 2 has parent 1 has parent 4. So 3 rows above. |
|  2 | 1      | 2 has parent 1 has parent 4. So 2 rows above.              |
|  1 | 4      | 1 has parent 4. So 1 row above.                            |
|  6 | 3      | 6 has parent 3. So 1 row above.                            |
|  4 | NULL   | No parent. So 0 rows above.                                |
|  3 | NULL   | No parent. So 0 rows above.                                |
+----+--------+------------------------------------------------------------+
因此,我想递归地计算一行的祖先数,并在此基础上排序。我该怎么做


编辑:我使用的是MySQL版本5.7.21。

您可以使用递归CTE来实现这一点,但是您没有列出您的MySQL版本,并且不是所有版本都可以做到这一点,因此这里有一些即使对于较旧的版本也应该有效的方法。这通过一个临时表和一个while语句来完成递归本身。构建临时表时,主表中的每条记录都有一条记录,主表保存父计数数据。首先,我们处理没有父项的所有记录,然后while中的查询处理下一代的所有记录。注意,语法可能有点错误,我已经有一段时间没有使用mysql了

--Create temp table to hold the parent count data
CREATE TEMPORARY TABLE ParentCount (id int, pcount int);

--First create a pcount record with count zero for all records with no parent
insert into ParentCount (id, pcount) Select id, 0 from TestData where parent is null;

--If we don't have a parentcount set for every record, keep going
-- This will run once for every level of depth
While (Select COUNT(id) from TestData) <> (Select COUNT(id) from ParentCount) Begin

    --add a pcount record for all rows that don't have one yet, but whose
    -- parents do have one (ie the next generation)
    insert into ParentCount (id, pcount)
    Select T.id, P.pcount + 1 as newpcount
    from TestData T 
        inner join ParentCount P on P.id = T.parent
        left outer join ParentCount P2 on P2.id = T.id
    where P2.id is null;
End;

--final query
Select T.id, T.parent 
from TestData T 
  inner join Parents P on T.id = p.id 
order by P.pcount DESC, T.id ASC;

为什么这个问题有-1票和2票来结束它?如果你投-1票,请详细说明,这样我就知道这个问题出了什么问题。这实际上似乎是一个很好的解决方案,尽管创建临时表似乎需要一些开销。由于我可以轻松地将MySQL实例更新为8.0.4版之前的版本,因此我想了解如何应用CTE。你能详细说明一下吗?这是一个关于这方面的文章的链接。它使用MicrosoftSQL语法而不是mysql,但原理是一样的。它讨论了使用递归CTE解决层次结构问题的不同方法。你的情况是一级的。递归CTE的工作原理基本上与我上面所做的非常相似——一个查询处理第一代级别,然后是第二个查询,重复处理下一代级别。它基本上一直在后台做临时表的事情,以最优化的方式进行查询,但是所发生的事情并没有什么不同。非常棒的内容,谢谢!我还发现了一篇很好的文章: