如何获取不含聚合列的字段值?以查询各国最年长者姓名为例
获取每个国家最年长者的姓名(仅返回姓名列)
先看我们的Customers表:
| first_name | last_name | age | country |
|---|---|---|---|
| John | Doe | 31 | USA |
| Robert | Luna | 22 | USA |
| David | Robinson | 22 | UK |
| John | Reinhardt | 25 | UK |
| Betty | Doe | 28 | UAE |
你原来写的查询SELECT first_name,last_name, MAX(age) FROM Customers GROUP BY country有问题:一是多数SQL环境里(比如开了ONLY_FULL_GROUP_BY的MySQL),SELECT里没被聚合的列必须出现在GROUP BY里,直接跑会报错;二是就算能跑,返回的姓名也不一定是对应国家最年长者的,结果完全不可靠。
要实现只返回每个国家最年长者的first_name和last_name,有两种靠谱的方法:
方法1:子查询关联(兼容所有SQL数据库)
先查出每个国家的最大年龄,再关联原表找到对应的人:
SELECT c.first_name, c.last_name FROM Customers c JOIN ( SELECT country, MAX(age) AS max_age FROM Customers GROUP BY country ) t ON c.country = t.country AND c.age = t.max_age;
如果某个国家有好几个人年龄都是最大的,这个查询会把他们都返回出来。
方法2:窗口函数(推荐,适合MySQL 8+、PostgreSQL、SQL Server等)
用窗口函数给每个国家的人按年龄降序排号,取排第一的那条:
SELECT first_name, last_name FROM ( SELECT first_name, last_name, ROW_NUMBER() OVER (PARTITION BY country ORDER BY age DESC) AS rn FROM Customers ) t WHERE rn = 1;
要是想保留同年龄的所有最年长者,把ROW_NUMBER()换成RANK()就行,这样同组里年龄相同的记录会拿到相同的排名,都会被筛选出来。
内容的提问来源于stack exchange,提问作者Innuendo
相关产品推荐
相关产品推荐

