我正在MySQL实例中使用Lahman Baseball Database。我想找到每年在全垒打(HR)中名列前茅的球员。Batting表具有以下架构(相关部分):

+-----------+----------------------+------+-----+---------+-------+
| Field     | Type                 | Null | Key | Default | Extra |
+-----------+----------------------+------+-----+---------+-------+
| playerID  | varchar(9)           | NO   | PRI |         |       |
| yearID    | smallint(4) unsigned | NO   | PRI | 0       |       |
| HR        | smallint(3) unsigned | YES  |     | NULL    |       |
+-----------+----------------------+------+-----+---------+-------+

每年,每个玩家都有一个条目(每年在数百到12k之间,可以追溯到1871年)。在一年内获得前N名击球手是很容易的:
SELECT playerID,yearID,HR
FROM Batting
WHERE yearID=2009
ORDER BY HR DESC LIMIT 3;
+-----------+--------+------+
| playerID  | yearID | HR   |
+-----------+--------+------+
| pujolal01 |   2009 |   47 |
| fieldpr01 |   2009 |   46 |
| howarry01 |   2009 |   45 |
+-----------+--------+------+

但我对每年的前三名感兴趣。我找到了类似this的解决方案,描述了如何从类别中选择顶部,并尝试将其应用到我的问题中,结果却得到了一个永远不会返回的查询:
SELECT
    b.yearID, b.playerID, b.HR
FROM
    Batting AS b
LEFT JOIN
    Batting b2
    ON
    (b.yearID=b2.yearID AND b.HR <= b2.HR)
GROUP BY b.yearID HAVING COUNT(*) <= 3;

我哪里做错了?

最佳答案

这样的做法应该管用:

SELECT b.playerID, b.yearID, b.HR
FROM Batting b
WHERE HR >= (
    SELECT b2.HR
    FROM Batting b2
    WHERE b2.yearID=b1.yearID
    ORDER BY b2.HR DESC
    LIMIT 2, 1
)
ORDER BY b.yearID DESC, b.HR DESC;

说明:请选择“本垒打次数>=为当年第三高”的所有行。这不会打破关系的。所以如果有一个以上的击球手有相同的本垒打次数,他们都会出现。
结果是从最近一年开始的排序,每年按排名进行排序。
注意:LIMIT是一个基于0的偏移量,所以2,1表示从第二行开始抓取一行,即:第三行。

关于sql - 我如何找到每年排名前N的击球手?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3063716/

10-11 07:52