订阅更新

每个帖子的评论数:同一张表里的帖子和评论

SQL 实战 123 题 · 第 83 题 简单 约 2 分钟读完

LeetCode 1241 · 自关联、去重计数、零值保留

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

把表拆成帖子(parent_id IS NULL)和评论两份,帖子 LEFT JOIN 评论,先 DISTINCT 出(帖子 ID, 评论 ID)对,再按帖子 COUNT(评论 ID)。去重处理重复行,LEFT JOIN 保留零评论帖子,COUNT 列名让零评论计为 0。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

提交表里既有帖子也有评论:帖子的父 ID 为空,评论的父 ID 指向所属帖子。表里可能有重复的帖子和重复的评论。统计每个帖子的不重复评论数(没有评论的帖子为 0),按帖子 ID 升序;指向已不存在帖子的评论不统计。

表结构

  • Submissions:sub_id、parent_id(帖子为空,评论为所属帖子 ID);没有主键,可能有重复行

思路

把同一张表当成两份:一份只取帖子(parent_id 为空),另一份当评论,用「帖子 ID = 评论的父 ID」左关联。以帖子为主表保证零评论的帖子也在;对帖子和评论分别去重,避免重复行导致多算。原文第二种写法先 DISTINCT(帖子, 评论)对,再计数,最清楚。

参考解法

写法 1:先统计每个父 ID 的评论数,再关联帖子

select s.sub_id post_id,ifnull(number_of_comments,0) number_of_comments
from Submissions s
left join (
  select parent_id ,count(distinct sub_id) number_of_comments
  from Submissions 
  group by parent_id
) t1
on s.sub_id = t1.parent_id
where s.parent_id  is null
group by post_id,number_of_comments
order by sub_id

写法 2:先去重(帖子, 评论)对,再按帖子计数

SELECT post_id, COUNT(sub_id) AS number_of_comments
FROM (
    SELECT DISTINCT post.sub_id AS post_id, sub.sub_id AS sub_id
    FROM Submissions post
    LEFT JOIN Submissions sub
    ON post.sub_id = sub.parent_id
    WHERE post.parent_id is null
) T
GROUP BY post_id
ORDER BY post_id ASC

易错点

  • 帖子本身有重复行,不去重会让结果里同一帖子出现多次。
  • 用 COUNT(*) 计数,零评论的帖子会被算成 1。
刷题进度保存在当前浏览器