MySQL:选择N行,但在一列中只有唯一值

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 /纽约

然而,由于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