Как мне найти лучшие N тестеров в год? - PullRequest
1 голос
/ 17 июня 2010

Я играю с Lahman Baseball Database в экземпляре MySQL.Я хочу найти игроков, которые превысили хоум-раны (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    |       |
+-----------+----------------------+------+-----+---------+-------+

Для каждого года у каждого игрока есть запись (от сотен до 12 тысяч в год, начиная с 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;

Где я ошибся?

Ответы [ 2 ]

3 голосов
/ 17 июня 2010

Примерно так: должно работать:

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 означает запуск после того, как вторая строка захватывает одну строку, т. Е. Третью строку.

0 голосов
/ 19 января 2011

Ух, случайно. Мне довелось сделать тот же запрос (хотя и о зарплатах) в БД Lahman Baseball, используя статью об эмуляции функций Oracle Analytic. Эта версия запроса является быстрой, но не такой интуитивно понятной.

select *
from (

select 
    b.yearID as year,
    b.teamID as team,
    m.nameFirst as first,
    m.nameLast as last,
    find_in_set(b.HR, x.teamRank) as rank,
    b.HR as HR


from 
    Batting b
    inner join Master m on m.playerID = b.playerID
    inner join (select yearID, group_concat(distinct HR order by HR desc) as teamRank from Batting group by yearID) x on x.yearID = b.yearID

) x

where 
    rank <= 10 and rank > 0 

order by    
    year desc, rank

Или 5 лучших показателей по персоналу на команду за 2010 год ...

select *
from (

select 
    b.yearID as year,
    b.teamID as team,
    m.nameFirst as first, 
    m.nameLast as last, 
    b.HR as HR,
    find_in_set(b.HR, x.teamRank) as rank

from 
    Batting b
    inner join Master m on m.playerID = b.playerID
    inner join (select teamID, group_concat(distinct HR order by HR desc) as teamRank from Batting where yearID = 2010 group by teamID) x on x.teamID = b.teamID
where 
    b.yearID = 2010
) x

where 
    rank <= 5 and rank > 0 

order by    
    team, rank

limit 12

Показывает эти результаты ...

year    team    first   last        HR  rank
2010    ARI Mark    Reynolds    32  1
2010    ARI Chris   Young       27  2
2010    ARI Kelly   Johnson     26  3
2010    ARI Adam    LaRoche     25  4
2010    ARI Justin  Upton       17  5
2010    ATL Brian   McCann      21  1
2010    ATL Jason   Heyward     18  2
2010    ATL Troy    Glaus       16  3
2010    ATL Martin  Prado       15  4
2010    ATL Eric    Hinske      11  5
2010    BAL Luke    Scott       27  1
2010    BAL Ty      Wigginton   22  2
...