You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用SQL实现艺术家歌曲统计及特征歌曲查询?是否需要使用子查询?

解决你的SQL查询需求:获取艺术家的歌曲统计及特色歌曲

嘿,我来帮你搞定这个SQL查询问题!你的需求是从lt.artist表中提取每个艺术家的歌曲数量,以及他们在流行度、声学特性、能量感三个维度上的代表性歌曲,当前的查询确实没法满足需求,我来给你拆解问题并提供两种可行的方案。

先说说你当前代码的问题

你的原查询:

SELECT artists AS artist, count(name) AS songs, name , acousticness, energy , popularity 
FROM lt.artist 
GROUP BY artists 
ORDER BY popularity DESC, acousticness DESC, energy DESC

这里有两个核心问题:

  1. GROUP BY 后的字段不匹配:按照SQL标准,SELECT列表里的非聚合字段(比如nameacousticness)必须出现在GROUP BY里,否则数据库要么报错(开启严格模式时),要么返回随机值,这显然不是你想要的对应维度的top歌曲。
  2. 没有按艺术家分组筛选维度top1:你只是做了全局排序,没法针对每个艺术家单独找出他们的最高流行度、最高声学特性的歌曲。

方案一:用窗口函数(推荐,高效清晰)

如果你的数据库支持窗口函数(比如MySQL 8.0+、PostgreSQL、SQL Server等),这是最优解,只需要扫描一次表就能完成所有计算:

WITH ranked_songs AS (
    SELECT
        artist,
        name AS song_name,
        acousticness,
        energy,
        popularity,
        -- 给每个艺术家的歌曲按流行度降序排名,行号1就是最流行的
        ROW_NUMBER() OVER (PARTITION BY artist ORDER BY popularity DESC) AS rn_pop,
        -- 按声学特性降序排名
        ROW_NUMBER() OVER (PARTITION BY artist ORDER BY acousticness DESC) AS rn_acoustic,
        -- 按能量值降序排名
        ROW_NUMBER() OVER (PARTITION BY artist ORDER BY energy DESC) AS rn_energy
    FROM lt.artist
)
SELECT
    artist,
    COUNT(DISTINCT song_name) AS song_count, -- 如果歌曲不会重复,用COUNT(*)也可以
    MAX(CASE WHEN rn_pop = 1 THEN song_name END) AS most_popular_song,
    MAX(CASE WHEN rn_acoustic = 1 THEN song_name END) AS most_acoustic_song,
    MAX(CASE WHEN rn_energy = 1 THEN song_name END) AS most_energised_artist_song
FROM ranked_songs
GROUP BY artist
ORDER BY artist;

代码解释

  • 首先用CTE(ranked_songs)给每个艺术家的每首歌做三个维度的排名,PARTITION BY artist确保排名是在每个艺术家的范围内进行的。
  • 主查询里,用COUNT统计每个艺术家的歌曲总数,再通过CASE配合MAX函数,把每个维度排名第一的歌曲名提取出来。

如果遇到同一维度有并列第一的歌曲(比如两首歌流行度相同),可以把ROW_NUMBER()换成RANK()或者DENSE_RANK(),这样并列的歌曲都会被标记为行号1,后续可以根据需求调整如何展示(比如用GROUP_CONCAT把并列歌曲拼起来)。

方案二:用子查询(兼容老版本数据库)

如果你的数据库不支持窗口函数(比如MySQL 5.7及更早版本),可以用子查询的方式实现,逻辑更直观:

SELECT
    a.artist,
    COUNT(*) AS song_count,
    -- 子查询获取当前艺术家最流行的歌曲
    (SELECT name FROM lt.artist a2 WHERE a2.artist = a.artist ORDER BY popularity DESC LIMIT 1) AS most_popular_song,
    -- 子查询获取当前艺术家最具声学特性的歌曲
    (SELECT name FROM lt.artist a2 WHERE a2.artist = a.artist ORDER BY acousticness DESC LIMIT 1) AS most_acoustic_song,
    -- 子查询获取当前艺术家最具能量感的歌曲
    (SELECT name FROM lt.artist a2 WHERE a2.artist = a.artist ORDER BY energy DESC LIMIT 1) AS most_energised_artist_song
FROM lt.artist a
GROUP BY a.artist
ORDER BY a.artist;

代码解释

每个子查询都针对当前艺术家,按指定维度降序排序后取第一首歌的名称,主查询负责统计每个艺术家的歌曲总数。不过这种方法在数据量大的时候性能会差一些,因为每个子查询都会单独扫描一次表。

最终效果

这两种方案都能输出你想要的格式:

artistsong_countmost_popular_songmost_acoustic_songmost_energised_artist_song
Justin Timberlake150MirrorsCry Me A RiverCan’t Stop The Feeling

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

火山引擎 最新活动