如何用单条SQL查询获取指定文章及其评论的所有关联评论?
当然可行!这种嵌套评论的需求,用**递归CTE(Common Table Expression)**就能通过单条SQL完美解决,刚好适配你这种自关联的表结构。
具体实现方案
递归CTE是处理层级自关联数据的标准工具,它分为「锚点查询」和「递归查询」两部分,一步步把顶层评论和所有子评论拉出来。
假设你的评论表名为comments,下面是针对指定文章ID(比如你示例中的33)的查询语句:
WITH RECURSIVE comment_tree AS ( -- 第一步:锚点查询,获取指定文章的所有顶层评论 -- 这里假设顶层评论的comment字段为NULL或0(表示没有父评论),根据你的实际数据调整 SELECT ID, article, comment AS parent_id, content, 1 AS depth -- 用depth标记层级,方便区分顶层/子评论 FROM comments WHERE article = 33 AND (comment IS NULL OR comment = 0) UNION ALL -- 第二步:递归查询,迭代获取所有子评论 SELECT c.ID, c.article, c.comment AS parent_id, c.content, ct.depth + 1 AS depth FROM comments c -- 关联CTE里的父评论,找到子评论 JOIN comment_tree ct ON c.comment = ct.ID ) -- 最终输出所有评论,按层级+ID排序更清晰 SELECT * FROM comment_tree ORDER BY depth, ID;
逻辑说明
- 锚点查询:先筛选出直接属于目标文章(
article=33)的顶层评论——也就是那些没有父评论的记录(根据你的数据结构调整comment字段的判断条件)。 - 递归查询:通过JOIN将子评论的
comment字段(父评论ID)和CTE中已获取的评论ID关联,循环拉取所有层级的子评论,同时用depth字段标记当前评论的层级(顶层为1,子评论+1)。 - 结果排序:最后按
depth和ID排序,能让顶层评论在前,子评论紧跟对应的父评论,结构更直观。
适配你的示例数据
比如你提到的示例:
- 前两行是
article=33的顶层评论(它们的comment字段应该是NULL/0) - 最后一行的
comment=2,而2是其中一条顶层评论的ID
这个查询会先把前两行作为锚点,然后递归找到关联的子评论,最终返回这三行,完全符合你的需求。
注意事项
- 确保你的数据库支持递归CTE:MySQL 8.0+、PostgreSQL、SQL Server、SQLite 3.35+等主流数据库都支持,老版本MySQL可能需要用其他方式(比如自连接多次,但递归CTE更优雅)。
- 调整
comment字段的判断条件:如果你的顶层评论的comment字段不是NULL/0,而是其他标识(比如不存在的ID),记得修改锚点查询里的条件。
内容的提问来源于stack exchange,提问作者miloszowi
相关产品推荐
相关产品推荐

