我正在玩弄 Lahman Baseball Database在 MySQL 实例中。我想找出每年全垒打 (HR) 最高的球员。击球表具有以下(相关部分)的架构:
+-----------+----------------------+------+-----+---------+-------+
| 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 |
+-----------+--------+------+
但我有兴趣从每年 中找出前 3 名。我找到了类似 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/