按外键递归次数排序 MySQL 查询结果

Sort MySQL Query results by amount of recursion in foreign keys

我有以下 table:

+----+--------+
| id | parent |
+----+--------+
|  1 | 4      |
|  2 | 1      |
|  3 | NULL   |
|  4 | NULL   |
|  5 | 2      |
|  6 | 3      |
+----+--------+

我希望table这样订购:

+----+--------+------------------------------------------------------------+
| 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 版本并且并非所有版本都可以这样做,所以这里有一些即使对于旧版本也应该适用的东西。这使用临时 table 和 while 语句进行递归本身。临时 table 为主 table 中的每条记录构建一条记录,主 table 保存父计数数据。首先,我们处理所有没有父项的记录,然后 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;