如何用SQL筛选共享某列值且另一列含指定值的多行数据
解决你的SQL筛选需求:找到共享列值且包含指定值的多行数据
看起来你想要从你的歌手-播放列表关联表中,筛选出那些共享同一个播放列表,并且该列表里包含你指定的若干歌手的所有条目——或者反过来,找出指定歌手共同所在的播放列表的相关行。我用你给出的示例数据,给你演示几种实用的实现方法:
场景1:获取所有属于「包含指定全部歌手」的播放列表的所有条目
比如你想找出所有在同时有Jay-Z和Imagine Dragons的播放列表里的行(从你的表来看,只有discover weekly符合这个条件),可以用子查询结合GROUP BY和HAVING来实现:
SELECT t.* FROM your_table t JOIN ( -- 先找出符合条件的播放列表:包含所有指定歌手 SELECT playlist FROM your_table WHERE name IN ('Jay-Z', 'Imagine Dragons') -- 替换成你要指定的若干值 GROUP BY playlist HAVING COUNT(DISTINCT name) = 2 -- 这里的数字要和你指定的元素数量一致 ) AS shared_playlists ON t.playlist = shared_playlists.playlist;
逻辑解释:
- 子查询部分:先筛选出包含你指定歌手的行,然后按播放列表分组,用
HAVING COUNT(DISTINCT name)确保这个列表里确实包含了你指定的所有歌手(避免重复条目干扰计数)。 - 外层查询将原表和筛选出的合格播放列表关联,得到所有属于这些列表的行——包括其他歌手(比如你的示例里的ZEDD)的条目。
场景2:只获取指定歌手在共享播放列表里的行
如果你只想看指定歌手(比如Jay-Z和Imagine Dragons)在他们共同播放列表里的行,不想包含其他歌手的,可以调整查询:
SELECT t.* FROM your_table t WHERE t.name IN ('Jay-Z', 'Imagine Dragons') AND t.playlist IN ( SELECT playlist FROM your_table WHERE name IN ('Jay-Z', 'Imagine Dragons') GROUP BY playlist HAVING COUNT(DISTINCT name) = 2 );
这个查询会返回Jay-Z和Imagine Dragons在discover weekly里的行,而ZEDD的条目会被排除在外。
另一种灵活方法:使用窗口函数
如果你习惯用窗口函数,也可以用CTE来实现,逻辑更直观:
WITH playlist_check AS ( SELECT *, -- 计算每个播放列表里包含的指定歌手数量 COUNT(DISTINCT CASE WHEN name IN ('Jay-Z', 'Imagine Dragons') THEN name END) OVER (PARTITION BY playlist) AS target_singer_count FROM your_table ) SELECT name, playlist FROM playlist_check WHERE target_singer_count = 2; -- 匹配指定的歌手数量
注意事项:
- 如果你的表存在重复条目(比如同一个歌手多次出现在同一个播放列表),一定要用
COUNT(DISTINCT name),否则重复的行会导致计数错误。 - 如果你指定的是更多歌手,只需要修改
IN里的列表,同时把HAVING或WHERE里的数字改成对应的数量即可。
内容的提问来源于stack exchange,提问作者Michal Vašíček
相关产品推荐
相关产品推荐

