运行此查询的表的结构大致如下:
comments_table(PK id, FK reply_to_id, content)
FK is a self join on itself
它在 10.4.27-MariaDB 上运行
数据看起来像这样:
+----+-------------+---------+
| id | reply_to_id | content |
+----+-------------+---------+
| 12 | NULL | text |
| 13 | 12 | text |
| 14 | 12 | text |
| 15 | 13 | text |
+----+-------------+---------+
查询应该按顺序检索输入父亲(或树根)中给出的所有回复注释。
结果顺序应该是深度优先。
预期结果示例:
Input : 12
Result: 13,15,14
12
/ \
13 14
\
15
+----+
| id |
|----+
| 13 |
| 15 |
| 14 |
+----+
等等
我想要存档的是在查询中完成此操作,而不使用任何外部代码。
我一直在尝试递归并修改如下所示的查询:
select id
from (
select * from comments order by id
) comments_sorted, (
select @pv := '62'
) initialisation
where find_in_set(replied_to_id, @pv)
and length(@pv := concat(@pv, ',', id));
查询确实有效并且它在输出中给出了对给定父亲(或树根)的所有回复
输出如下所示:
+----+
| id |
+----+
| 13 |
| 14 |
| 15 |
+----+
同时所需的输出如上所示
如何才能实现?
编辑
提供额外反馈
将您的查询@Luuk 与这组数据一起使用:
+----+---------------+
| id | replied_to_id |
+----+---------------+
| 81 | NULL |
| 82 | NULL |
| 83 | 82 |
| 84 | 83 |
| 85 | 83 |
| 86 | 83 |
| 87 | 84 |
| 88 | 87 |
| 93 | 88 |
+----+---------------+
我得到这个结果:
+---+----+---------------+
| x | id | replied_to_id |
+---+----+---------------+
| 1 | 83 | 82 |
| 1 | 84 | 83 |
| 1 | 85 | 83 |
| 1 | 86 | 83 |
| 1 | 87 | 84 |
| 1 | 88 | 87 |
| 1 | 93 | 88 |
+---+----+---------------+
我可以看到 x 值没有增加。
我使用的查询是:
WITH RECURSIVE cte AS (
SELECT row_number() over (order by id) as x, id, replied_to_id
FROM comments
WHERE replied_to_id=82
UNION ALL
SELECT x, comments.id, comments.replied_to_id
FROM cte
INNER JOIN comments on comments.replied_to_id = cte.id
)
SELECT * FROM cte ORDER BY x,id;
可能是什么?
WITH RECURSIVE cte AS (
SELECT
row_number() over (order by id) as x,
id,
reply_to_id
FROM test
WHERE reply_to_id=12
UNION ALL
SELECT x, test.id, test.reply_to_id
FROM cte
INNER JOIN test on test.reply_to_id = cte.id
)
SELECT *
FROM cte
ORDER BY x,id;
参见:DBFIDDLE
row_number()
对第一级的回复进行排序,并且此排序将复制到下一级。
输出:
x | id | 回复id |
---|---|---|
1 | 13 | 12 |
1 | 15 | 13 |
2 | 14 | 12 |
这是另一种方法,使用路径来排序数据:
WITH recursive cte (id, reply_to_id, path)
AS
(
SELECT id, reply_to_id, CAST(id AS CHAR(200)) AS path
FROM comments_table
WHERE reply_to_id = 12
UNION ALL
SELECT e.id, e.reply_to_id, CONCAT(cte.path, ",", e.id)
FROM comments_table AS e
JOIN cte ON e.reply_to_id = cte.id
)
SELECT *
from cte
order by path