我的网站 ( privacyfirstproducts.com ) 上有一个评论部分,我很乐意以这种结构显示评论(就像黑客新闻一样):
comment 1 (10 upvotes)
comment 4 (reply on comment 1, 7 upvotes)
comment 5 (reply on comment 1, 5 upvotes)
comment 8 (reply on comment 5, 8 upvotes)
...
comment 9 (reply on comment 1, 3 upvotes)
comment 3 (reply on comment 1, 0 upvotes)
comment 10 (reply on comment 1, 0 upvotes)
...
comment 6 (2 upvotes)
comment 7 (reply on comment 3, 2 upvotes)
comment 2 (0 upvotes)
...
我有这个 postgresql comments
-table:
comment_id | original_id | upvotes | text | ...
------------------------------------------------------
1 | NULL | 10 | Hi.. | ...
2 | NULL | 0 | Je.. | ...
3 | 1 | 0 | Di.. | ...
4 | 1 | 7 | Si.. | ...
5 | 1 | 5 | Op.. | ...
6 | NULL | 2 | Op.. | ...
7 | 6 | 2 | Op.. | ...
8 | 5 | 8 | Op.. | ...
9 | 1 | 3 | Op.. | ...
10 | 1 | 0 | Th.. | ...
我很乐意将其作为 postgresql 的输出:
comment_id | original_id | upvotes | deep | text | ...
------------------------------------------------------
1 | NULL | 10 | 0 | Hi.. | ...
4 | 1 | 7 | 1 | Si.. | ...
5 | 1 | 5 | 1 | Op.. | ...
8 | 5 | 8 | 2 | Op.. | ...
9 | 1 | 3 | 1 | Op.. | ...
3 | 1 | 0 | 1 | Di.. | ...
10 | 1 | 0 | 1 | Th.. | ...
6 | NULL | 2 | 0 | Op.. | ...
7 | 6 | 2 | 1 | Op.. | ...
2 | NULL | 0 | 0 | Je.. | ...
我认为这应该通过递归来完成,但我不知道该怎么做。
最佳答案
递归查询记录在 CTE 中手册的一部分。
您首先选择根行(在您的例子中,是顶级评论;original_id IS NULL
的评论)。
递归查询的第二部分(在下面示例中的 UNION
之后)将子评论与已经找到的评论连接起来。它会自动重复,直到找不到更多行。在您的情况下,第二个选择需要在 child.original_id = parent.comment_id
上加入 child 对 parent 的评论。
找到每个 Node 的深度
很容易 - 只需在进行第二次选择时将父行的深度加 1。
比较棘手的部分是获得您需要的排序顺序(按投票和 ID,保持评论按父组分组)。这可以通过在数组(下例中的 path
列)中累积投票以及每个评论的祖先 ID,然后按数组对行进行排序来完成。请注意,示例中的投票计数已被否定,以便首先对较高的值进行排序。这可以通过对 DESC
进行排序来完成,但是当评论具有相同的票数时,评论 ID 必须取反才能首先对较早的评论进行排序。
WITH RECURSIVE comment_tree AS (
-- First select performed to get top level rows
SELECT
comment_id,
original_id,
upvotes,
text,
0 depth, -- depth in the tree
ARRAY[-upvotes, comment_id] path -- used to sort by vote then ID
FROM comment WHERE original_id IS NULL
UNION
-- Self referential select performed repeatedly until no more rows are found
SELECT
c.comment_id,
c.original_id,
c.upvotes,
c.text,
ct.depth + 1,
ct.path || ARRAY[-c.upvotes, c.comment_id]
FROM comment c
JOIN comment_tree ct ON c.original_id = ct.comment_id
)
SELECT * FROM comment_tree ORDER BY path;
关于javascript - 如何显示基于赞成票的递归评论?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53362825/