实现收藏排行需先设计 favorites 表(含 user_id、item_id、item_type 等字段),再通过 GROUP BY COUNT 统计并按次数降序排列;可关联主表补充信息,加时间 / 状态等条件筛选,并用复合索引或预计算优化性能。

要实现收藏排行,核心是统计每个内容被收藏的次数,再按次数降序 排列。MySQL 本身不提供“收藏”表结构,所以需要先有合理的数据表设计,再通过聚合查询拿到排行结果。
收藏表结构设计要点
典型场景中,收藏行为通常涉及两个主体:用户(user)和被收藏的内容(如文章、商品、视频等)。推荐使用一张独立的收藏关系表,例如:
- favorites 表:包含 user_id(收藏者)、item_id(被收藏对象 ID)、item_type(可选,用于区分文章 / 商品等类型)、created_at(时间戳)
- 确保 (user_id, item_id, item_type) 组合唯一,避免重复收藏
- 为 item_id 和 item_type 建联合索引,提升分组统计效率
基础收藏排行查询语句
假设你要查“所有文章”的收藏数排行(item_type = ‘article’),直接用 GROUP BY + COUNT 即可:
SELECT item_id AS article_id, COUNT(*) AS favorite_count FROM favorites WHERE item_type = 'article' GROUP BY item_id ORDER BY favorite_count DESC LIMIT 10;
这条语句返回收藏数最高的前 10 篇文章 ID 及对应次数。如果还需展示文章标题等信息,可 LEFT JOIN 文章主表(如 articles):
SELECT a.id, a.title, COUNT(f.item_id) AS favorite_count FROM articles a LEFT JOIN favorites f ON f.item_id = a.id AND f.item_type = 'article' GROUP BY a.id, a.title ORDER BY favorite_count DESC LIMIT 10;
支持多维度筛选的进阶写法
实际业务中常需限定时间范围(如“近 7 天收藏榜”)或排除无效用户(如封禁用户、测试账号):
- 加时间条件:
AND f.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) - 排除特定用户:
AND f.user_id NOT IN (1001, 1002)或关联用户状态表过滤 - 只统计有效收藏(如未取消):可在 favorites 表中增加 is_active 字段,默认为 1,取消时设为 0
示例(7 天内活跃用户的收藏排行):
SELECT f.item_id, COUNT(*) AS favorite_count FROM favorites f INNER JOIN users u ON f.user_id = u.id WHERE f.item_type = 'article' AND f.is_active = 1 AND u.status = 'active' AND f.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY f.item_id ORDER BY favorite_count DESC LIMIT 10;
性能优化建议
当收藏量达百万级后,单纯 GROUP BY 可能变慢。可考虑:
- 在 item_type, item_id, is_active, created_at 上建立复合索引
- 对高频访问的排行榜(如日榜、周榜),用定时任务将结果预计算并存入 rankings 表,查询时直取
- 若实时性要求不高,可用 Redis 缓存 TOP-N 结果,减轻数据库压力
不复杂但容易忽略的是:确保 WHERE 条件中的字段都有索引支撑,否则 COUNT + GROUP BY 会触发全表扫描。