一、采用id,parent_id(父节点id)来存储
1、表结构如下:
2、假设表中数据为:
3、想实现的效果如下,打开评论显示第一张页面,即查询所有一级评论,点击“展开1440条回复”查询对应一级评论前三条评论,
4、当查询对应一级评论前三条评论时(这里按照创建时间正序排序,当然也可以按点赞数倒序排序),就需要进行递归查询。
-- 分页查询一级评论,查询前20条
-- SELECT * FROM tb_comments WHERE parent_id = 0 LIMIT 0,20;
-- 当点击“展开1440条回复”时,比如我想查询前3条,就需要进行递归查询,不管是在java代码里递归还是在数据库递归
WITH RECURSIVE comment_tree AS (
-- 锚点:获取目标评论
SELECT *,0 as replied_user_id, 1 AS depth
FROM tb_comments
WHERE parent_id = 1
UNION ALL
-- 递归获取所有后代评论
SELECT c.*, ct.user_id AS replied_user_id, ct.depth + 1
FROM tb_comments c
INNER JOIN comment_tree ct ON c.parent_id = ct.id
)
SELECT * FROM comment_tree
ORDER BY create_time ASC
LIMIT 3;
递归查询结果如下:
缺点:如果用户互相回复层级过多,那么递归查询效率过低,因此重新设计表结构。
二、采用id,parent_id(顶级评论id),reply_id(回复评论id)存储
1、表结构:
2、数据
3、如果想实现如下效果,那么查询过程为:
-- 分页查询一级评论,查询前20条
-- SELECT * FROM tb_comments WHERE parent_id = 0 LIMIT 0,20;
-- 当点击“展开1440条回复”时,比如我想查询前3条,直接查询一层评论的所有子节点即可
SELECT t1.*,
CASE
WHEN t2.parent_id = 0 THEN
0 ELSE t2.user_id
END AS replied_user_id
FROM
tb_comments t1
LEFT JOIN tb_comments t2 ON t1.reply_id = t2.id
WHERE
t1.parent_id = 1
ORDER BY
create_time
LIMIT 0,3
查询结果:
由此可看,不采用递归也能实现上述效果,而且效率高一些。
【注】方案二还适用于引用评论进行回复。