Bla*_*laM 34 mysql sql unique aggregate-functions min
鉴于此数据集:
ID Name City Birthyear
1 Egon Spengler New York 1957
2 Mac Taylor New York 1955
3 Sarah Connor Los Angeles 1959
4 Jean-Luc Picard La Barre 2305
5 Ellen Ripley Nostromo 2092
6 James T. Kirk Riverside 2233
7 Henry Jones Chicago 1899
Run Code Online (Sandbox Code Playgroud)
我需要找到3个最老的人,但每个城市只有一个.
如果它只是三个最古老的,它将是......
然而,由于Egon Spengler和Mac Taylor都位于纽约,Egon Spengler将退出,而下一个(Sarah Connor /洛杉矶)将会进入.
优雅的解决方案?
更新:
目前PConroy的变体是最好/最快的解决方案:
SELECT P.*, COUNT(*) AS ct
FROM people P
JOIN (SELECT MIN(Birthyear) AS Birthyear
FROM people
GROUP by City) P2 ON P2.Birthyear = P.Birthyear
GROUP BY P.City
ORDER BY P.Birthyear ASC
LIMIT 10;
Run Code Online (Sandbox Code Playgroud)
他使用"IN"的原始查询对于大数据集来说极其缓慢(在5分钟后中止),但是将子查询移动到JOIN会加快它的速度.约需0.15秒.我的测试环境中有1 mio行.我有一个关于"City,Birthyear"的索引和第二个关于"Birthyear"的索引.
注意:这与...有关
Con*_*oyP 18
可能不是最优雅的解决方案,并且IN可能会在较大的桌子上受到影响.
嵌套查询获得Birthyear每个城市的最小值.只有具有此内容的记录Birthyear在外部查询中匹配.按年龄排序然后限制为3个结果让你成为他们城市中最老的3个最老的人(Egon Spengler退出..)
SELECT Name, City, Birthyear, COUNT(*) AS ct
FROM table
WHERE Birthyear IN (SELECT MIN(Birthyear)
FROM table
GROUP by City)
GROUP BY City
ORDER BY Birthyear DESC LIMIT 3;
+-----------------+-------------+------+----+
| name | city | year | ct |
+-----------------+-------------+------+----+
| Henry Jones | Chicago | 1899 | 1 |
| Mac Taylor | New York | 1955 | 1 |
| Sarah Connor | Los Angeles | 1959 | 1 |
+-----------------+-------------+------+----+
Run Code Online (Sandbox Code Playgroud)
编辑 - 添加GROUP BY City到外部查询,因为具有相同出生年份的人将返回多个值.对外部查询进行分组可确保每个城市只返回一个结果,如果有多个人具有该最小值Birthyear.该ct列将显示城市中是否存在多个人Birthyear