如何先执行ORDER BY排序再执行GROUP BY分组?
实现先排序再分组的SQL调整方案
你的需求是先按scrap_date降序排序,再按website_ID分组,取每个website_ID对应的最新记录,原SQL的问题是GROUP BY会先于ORDER BY执行,且直接SELECT saf.*会导致非分组列的取值不可控。以下是两种可行的调整方案:
方案1:使用窗口函数(推荐,适用于MySQL 8+、PostgreSQL、SQL Server等支持窗口函数的数据库)
通过ROW_NUMBER()窗口函数,按website_ID分组后给每条记录按scrap_date降序编号,然后取编号为1的记录(即每个分组的最新一条):
SELECT * FROM ( SELECT saf.*, ROW_NUMBER() OVER (PARTITION BY saf.website_ID ORDER BY saf.scrap_date DESC) AS rn FROM sm_artists_followers saf JOIN sm_artists_meta sam ON saf.artist_ID = sam.artist_ID WHERE sam.fk_sm_artist_id = 13 AND DATE(saf.scrap_date) = '2023-10-22' ) t WHERE rn = 1;
方案2:子查询关联(兼容低版本MySQL等不支持窗口函数的数据库)
先筛选出每个website_ID对应的最大scrap_date,再关联原表获取完整记录:
SELECT saf.* FROM sm_artists_followers saf JOIN sm_artists_meta sam ON saf.artist_ID = sam.artist_ID JOIN ( SELECT website_ID, MAX(scrap_date) AS max_scrap_date FROM sm_artists_followers WHERE artist_ID IN (SELECT artist_ID FROM sm_artists_meta WHERE fk_sm_artist_id = 13) AND DATE(scrap_date) = '2023-10-22' GROUP BY website_ID ) t ON saf.website_ID = t.website_ID AND saf.scrap_date = t.max_scrap_date WHERE sam.fk_sm_artist_id = 13 AND DATE(saf.scrap_date) = '2023-10-22';
补充说明:
- 原SQL使用的隐式JOIN(逗号分隔表)已改为显式
JOIN语法,可读性更强。 - 两种方案本质都是先锁定每个
website_ID的最新记录,再获取对应数据,等价于实现“先排序取最新,再按分组保留目标记录”的逻辑。
内容的提问来源于stack exchange,提问作者skcrpk
相关产品推荐
相关产品推荐

