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

MySQL查询返回全量歌曲并标识用户是否已拥有该歌曲

解决SELECT查询中返回存在标识字段且避免重复的问题

你的问题很典型——当关联用户歌曲表来添加hasSong标识时,原本的去重逻辑失效了,本质原因是hasSong的存在让原本相同的歌曲行产生了差异,DISTINCT无法再合并它们。下面给你两种可靠的解决方案:

方法一:LEFT JOIN + GROUP BY(适合需扩展获取关联表字段的场景)

通过左关联用户歌曲表,再按歌曲的唯一信息分组,用聚合函数判断是否存在匹配记录:

SELECT 
    song.id AS id_song,
    CONCAT(song.article, ' ', song.name) AS name,
    -- 用COUNT判断是否有匹配的用户歌曲记录,返回1或0
    CASE WHEN COUNT(user_song.id) > 0 THEN 1 ELSE 0 END AS hasSong
FROM song
-- 关联时直接限定用户ID,避免无关记录干扰
LEFT JOIN user_song 
    ON song.id = user_song.song_id 
    AND user_song.user_id = 123 -- 替换为你的目标用户ID
WHERE song.source = '指定来源' -- 替换为你的目标来源
-- 按歌曲的唯一标识分组,确保每个歌曲只返回一行
GROUP BY song.id, song.article, song.name;

这种方式的好处是,如果后续需要从user_song表获取其他字段(比如收藏时间),可以直接在SELECT里添加对应的聚合函数(比如MAX(user_song.created_at))。

方法二:EXISTS子查询(简洁高效,仅判断存在性)

如果只需要判断用户是否拥有该歌曲,用EXISTS子查询会更直接,而且性能通常更好(因为子查询找到匹配项就会停止检索):

SELECT 
    song.id AS id_song,
    CONCAT(song.article, ' ', song.name) AS name,
    -- EXISTS返回布尔值,数据库通常会转为1(存在)或0(不存在)
    EXISTS (
        SELECT 1 
        FROM user_song 
        WHERE user_song.song_id = song.id 
          AND user_song.user_id = 123 -- 替换为你的目标用户ID
    ) AS hasSong
FROM song
WHERE song.source = '指定来源'; -- 替换为你的目标来源

这种写法不需要分组,逻辑更清晰,每个歌曲必然只返回一行,完全不会出现重复问题。

小提示

记得把SQL里的123和'指定来源'替换为你实际的用户ID和来源值。另外如果使用MySQL,要确保你的GROUP BY语句符合ONLY_FULL_GROUP_BY模式的要求(也就是所有非聚合字段都要出现在GROUP BY里)。

内容的提问来源于stack exchange,提问作者Renan Aguiar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:13:56