如何按CITY和PROD分组查询并保留P1、P2列及最小P3值
解决分组取最小P3并保留对应P1、P2的问题
这个场景太常见了!GROUP BY确实只能返回你指定的分组字段和聚合计算结果,没法直接把P1、P2这类非分组列带回来。我给你几个实用的解决方案,你可以根据自己用的数据库版本和具体需求来选:
1. 窗口函数法(推荐,适配现代数据库)
如果你的数据库支持窗口函数(比如MySQL 8.0+、PostgreSQL、SQL Server、Oracle等),这是最简洁易维护的方法。我们可以用ROW_NUMBER()或者RANK()函数,按CITY和PROD分区,再按P3升序排序,最后筛选出每组的第一条记录:
WITH ranked_data AS ( SELECT CITY, PROD, P1, P2, P3, -- 按CITY+PROD分组,P3最小的行排第1 ROW_NUMBER() OVER (PARTITION BY CITY, PROD ORDER BY P3 ASC) AS row_num FROM MYTABLE ) SELECT CITY, PROD, P1, P2, P3 FROM ranked_data WHERE row_num = 1;
注意:如果同一组内有多行的P3都是最小值,ROW_NUMBER()会随机选其中一行返回。要是想保留所有P3为组内最小值的行,把ROW_NUMBER()换成RANK()即可。
2. 子查询关联法(兼容旧版本数据库)
如果你的数据库版本较低(比如MySQL 5.x)不支持窗口函数,可以先通过子查询找出每组的最小P3,再和原表关联匹配,从而拿到对应的P1、P2:
SELECT t.CITY, t.PROD, t.P1, t.P2, t.P3 FROM MYTABLE t INNER JOIN ( -- 先分组获取每组的最小P3 SELECT CITY, PROD, MIN(P3) AS min_p3 FROM MYTABLE GROUP BY CITY, PROD ) g ON t.CITY = g.CITY AND t.PROD = g.PROD AND t.P3 = g.min_p3;
这种方法会返回所有P3等于组内最小值的行,和RANK()的效果一致。
3. IN子句法(写法更简洁)
逻辑和关联法类似,用多列IN子句来匹配分组和最小P3的组合:
SELECT CITY, PROD, P1, P2, P3 FROM MYTABLE WHERE (CITY, PROD, P3) IN ( SELECT CITY, PROD, MIN(P3) FROM MYTABLE GROUP BY CITY, PROD );
不过要注意,部分旧数据库可能不支持多列IN的语法,使用前可以先测试一下。
内容的提问来源于stack exchange,提问作者S12000
相关产品推荐
相关产品推荐

