多表JOIN查询MIN与MAX值时关联字段信息错误的技术咨询
解决关联多表时MIN/MAX值对应字段错误的问题
我来帮你搞定这个问题!你遇到的情况其实很常见——你的SQL确实算出了正确的最长和最短歌曲时长,但其他字段(歌曲名、专辑名、艺术家名)完全不对,这是因为你没把聚合出来的最值和对应的具体歌曲记录绑定起来。
原SQL的问题分析
你原来的写法里,第一个SELECT用MAX(SONG.LENGTH_SECONDS)时,数据库只会返回整个表中最长的时长数值,但SONG_NAME、ALBUM_NAME这些字段是随机从某条歌曲记录里挑的,根本不是那条最长歌曲的信息;第二个SELECT用MIN()时也是一样的道理。最后用UNION把这两个“半对”的结果拼起来,自然就出现了时长正确但其他信息驴唇不对马嘴的情况。
正确的解决方案
方法1:用子查询筛选对应最值的歌曲
先找到最长和最短的时长值,再筛选出匹配这些时长的歌曲,最后关联专辑和艺术家表获取完整信息:
SELECT s.SONG_NAME, a.ALBUM_NAME, ar.ARTIST_NAME, s.LENGTH_SECONDS AS LENGTH FROM SONG s JOIN ALBUM a ON a.ALBUM_ID = s.ALBUM_ID JOIN ARTIST ar ON ar.ARTIST_ID = s.ARTIST_ID WHERE s.LENGTH_SECONDS IN ( SELECT MAX(LENGTH_SECONDS) FROM SONG UNION SELECT MIN(LENGTH_SECONDS) FROM SONG );
方法2:用窗口函数标记最值记录(推荐)
如果你的数据库支持窗口函数(比如MySQL 8+、PostgreSQL、SQL Server等),这种写法更灵活,还能轻松处理有多首歌曲并列最长/最短的场景:
WITH SongLengths AS ( SELECT s.SONG_NAME, a.ALBUM_NAME, ar.ARTIST_NAME, s.LENGTH_SECONDS, -- 标记最长的歌曲(如果并列,ROW_NUMBER会只选一个,换成RANK()会选所有) ROW_NUMBER() OVER (ORDER BY s.LENGTH_SECONDS DESC) AS rn_max, -- 标记最短的歌曲 ROW_NUMBER() OVER (ORDER BY s.LENGTH_SECONDS ASC) AS rn_min FROM SONG s JOIN ALBUM a ON a.ALBUM_ID = s.ALBUM_ID JOIN ARTIST ar ON ar.ARTIST_ID = s.ARTIST_ID ) SELECT SONG_NAME, ALBUM_NAME, ARTIST_NAME, LENGTH_SECONDS AS LENGTH FROM SongLengths WHERE rn_max = 1 OR rn_min = 1;
如果需要保留所有并列的最长/最短歌曲,把ROW_NUMBER()换成RANK()即可。
内容的提问来源于stack exchange,提问作者Zep
相关产品推荐
相关产品推荐

