按外键递归次数排序 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;
我有以下 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;