MySQL如何统计列值计数并关联查询另一列指定值,实现帖子点赞数与状态查询
方案实现及优化建议
前提表结构约定
先统一两个表的核心字段,避免实现逻辑出现歧义:
- Post表(帖子表)核心字段:
post_id(主键)、content、publish_time等业务字段 - Like表(点赞记录表)核心字段:
like_id(主键)、post_id(关联帖子ID)、user_id(点赞用户ID),建议新增(post_id, user_id)联合唯一索引避免重复点赞
方案1:单SQL关联查询(优先推荐,性能更好)
简化版实现(无需多次子查询关联)
直接通过条件聚合一次得到点赞数和用户点赞状态,写法更简洁,性能和多次join的方式一致:
-- 假设当前登录用户ID为1001,查询最新发布的10条帖子 SELECT p.*, COUNT(l.post_id) AS like_count, MAX(IF(l.user_id = 1001, 1, 0)) AS is_liked FROM Post p LEFT JOIN `Like` l ON p.post_id = l.post_id GROUP BY p.post_id ORDER BY p.publish_time DESC LIMIT 10;
逻辑说明:
- 用LEFT JOIN保证没有点赞的帖子也能正常返回
COUNT(l.post_id)统计总点赞数:没有点赞的帖子关联后l.post_id为NULL,COUNT会自动忽略,返回值为0MAX(IF(l.user_id = 1001,1,0))判断当前用户点赞状态:如果存在该用户的点赞记录,IF函数会返回1,MAX取最大值后得到1表示已点赞,否则为0表示未点赞
按你提出的“分别统计再join”思路实现
如果需要把点赞统计和用户状态查询拆分到子查询,也可以用下面的写法,结果和上面一致:
SELECT p.*, IFNULL(lc.like_count, 0) AS like_count, IF(ul.post_id IS NOT NULL, 1, 0) AS is_liked FROM Post p LEFT JOIN ( SELECT post_id, COUNT(*) AS like_count FROM `Like` GROUP BY post_id ) lc ON p.post_id = lc.post_id LEFT JOIN ( SELECT post_id FROM `Like` WHERE user_id = 1001 ) ul ON p.post_id = ul.post_id ORDER BY p.publish_time DESC LIMIT 10;
方案2:两次MySQL查询实现
适合不熟悉复杂SQL、或者有业务分层要求的场景,实现逻辑更直观:
- 第一次查询:获取10条帖子和对应总点赞数
SELECT p.*, IFNULL(COUNT(l.post_id),0) AS like_count FROM Post p LEFT JOIN `Like` l ON p.post_id = l.post_id GROUP BY p.post_id ORDER BY p.publish_time DESC LIMIT 10;
- 拿到查询到的10条帖子的post_id列表,拼成IN查询的参数,第二次查询当前用户对这批帖子的点赞记录:
-- 示例中IN后的参数为第一步查询得到的post_id集合 SELECT post_id FROM `Like` WHERE user_id = 1001 AND post_id IN (1,2,3,4,5,6,7,8,9,10);
- 代码层做字段匹配:如果帖子的post_id存在于第二步返回的结果中,
is_liked设为1,否则设为0即可。
高并发场景下的更优方案
如果数据量较大、查询QPS高,可以通过字段冗余进一步提升性能:
在Post表新增like_count冗余字段,每次用户点赞/取消点赞时同步更新这个字段的值,查询时就不需要每次聚合统计Like表,SQL可以简化为无聚合的全索引查询,性能提升数倍:
SELECT p.*, IF(l.post_id IS NOT NULL,1,0) AS is_liked FROM Post p LEFT JOIN `Like` l ON p.post_id = l.post_id AND l.user_id = 1001 ORDER BY p.publish_time DESC LIMIT 10;
内容的提问来源于stack exchange,提问作者dfassf
相关产品推荐
相关产品推荐

