You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL技术需求:随机取20篇文章并限制单用户文章数量上限

解决随机展示文章时单用户占比过高的问题

嘿,这个场景我之前做内容推荐的时候碰到过——既要随机选20篇文章,又得避免某个用户的内容霸屏,限制单用户最多3或4篇。下面给你几个实用的解决方案,适配不同的数据库版本:

方案一:用窗口函数(推荐,适合MySQL 8+/PostgreSQL等支持窗口函数的数据库)

这个方法逻辑清晰,性能也不错。先给每个用户的文章做随机排序,只保留前N篇(这里N是3或4),再从这些筛选后的文章里随机挑20篇。

WITH user_limited_articles AS (
    SELECT 
        a.article_id,
        a.user_id,
        a.title,
        a.description,
        -- 按用户分组,组内随机排序,给每条记录标序号
        ROW_NUMBER() OVER (PARTITION BY a.user_id ORDER BY RAND()) AS row_num
    FROM articles a
)
SELECT article_id, user_id, title, description
FROM user_limited_articles
WHERE row_num <= 3 -- 这里改成4就是限制单用户最多4篇
ORDER BY RAND()
LIMIT 20;

原理说明:

  1. 第一步通过ROW_NUMBER()窗口函数,把每个用户的文章随机打乱后编号,每个用户只保留编号≤3的文章;
  2. 第二步从这些“按用户限制数量”后的文章里,再次随机排序取20篇,保证整体展示的随机性。

方案二:兼容老版本MySQL(无窗口函数/CTE支持)

如果你的数据库版本比较老,不支持CTE和窗口函数,可以用子查询的方式实现:

SELECT a.*
FROM (
    -- 先给所有文章生成随机值
    SELECT *, RAND() AS random_score
    FROM articles
) a
WHERE (
    -- 统计当前用户下,随机值≥当前文章的数量,控制不超过3
    SELECT COUNT(*)
    FROM (SELECT *, RAND() AS random_score FROM articles) a2
    WHERE a2.user_id = a.user_id AND a2.random_score >= a.random_score
) <= 3
ORDER BY RAND()
LIMIT 20;

注意事项:

  • 这个方法因为每次子查询都要生成随机值,数据量大的时候性能会差一些,适合小数据量场景;
  • 如果想改成限制4篇,把<=3改成<=4就行。

额外优化建议

  • 如果你的articles表数据量很大,ORDER BY RAND()会导致全表扫描和排序,性能不佳。可以考虑用主键随机法替代,比如先随机生成一个主键范围,再筛选符合条件的文章,最后补全数量;
  • 如果存在“符合条件的文章总数不足20”的情况,业务上可以考虑放宽单用户限制,或者返回所有符合条件的文章,根据实际需求调整。

内容的提问来源于stack exchange,提问作者Mohan Jedaro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:19:24