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

MariaDB 10.1.29单查询获取Top3热门歌曲+3首非热门随机歌曲

解决方案:合并最受欢迎歌曲与随机歌曲

针对你的MariaDB 10.1.29版本限制,我们可以通过用户变量排名结合UNION ALL来实现需求,既规避子查询LIMIT的问题,又能精确获取两组目标数据:

(
    -- 第一部分:3首最受欢迎的歌曲(按liked降序取前3)
    SELECT song_id, name, liked
    FROM (
        SELECT 
            song_id, 
            name, 
            liked, 
            @rank := @rank + 1 AS rank
        FROM song, (SELECT @rank := 0) AS init_rank
        ORDER BY liked DESC
    ) AS ranked_songs
    WHERE rank <= 3
)
UNION ALL
(
    -- 第二部分:3首不在前3范围内的随机歌曲
    SELECT song_id, name, liked
    FROM (
        SELECT 
            song_id, 
            name, 
            liked, 
            @rank2 := @rank2 + 1 AS rank
        FROM song, (SELECT @rank2 := 0) AS init_rank2
        ORDER BY liked DESC
    ) AS ranked_songs
    WHERE rank > 3
    ORDER BY RAND()
    LIMIT 3
)
ORDER BY 
    -- 可选:让结果先显示最受欢迎组,再显示随机组
    CASE WHEN rank <=3 THEN 1 ELSE 2 END;

为什么你的尝试语句无效?

我们来拆解你遇到的核心问题:

  1. 第一个查询的问题:
    你用笛卡尔积关联主表和前3歌曲的子查询,这会导致非前3的歌曲与前3的每一行都匹配,产生大量重复行。最后LIMIT 3拿到的可能是重复数据,逻辑完全偏离需求。正确的思路应该是拆分两组数据分别查询,再合并结果。

  2. 第二个查询的问题:
    NOT IN(b.ids)中的b.ids是一个逗号分隔的字符串(比如"6,8,5"),而NOT IN需要的是独立值列表。数据库会把整个字符串当作单个值去匹配,自然找不到符合条件的歌曲。你可以改用FIND_IN_SET(a.song_id, b.ids) = 0来检查song_id是否不在这个字符串里,但这种方式不如变量排名可靠(比如GROUP_CONCAT有长度限制)。

额外说明

  • 如果你的song_id是主键,变量排名的方式可以确保精确取到前3首最受欢迎的歌曲,即使存在liked值并列的情况。
  • ORDER BY RAND()在数据量较大时性能会下降,但如果你的表数据量不大,这个写法完全够用。

内容的提问来源于stack exchange,提问作者Kien Pham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:14:21