2014-01-04 2 views
1

У меня есть простое расширение проблемы с наибольшей n-группой.most-n-per-group, где внутреннее соединение уже существует

Вот мой запрос:

$q = 
'SELECT    
    played.words, MAX(played.score) max_score, played.longest, played.game_options, 
    users.first_name 
FROM played 
INNER JOIN users 
ON played.user_id = users.user_id  
GROUP BY game_options 
'; 

К сожалению, в то время как я всегда получаю максимальное количество баллов для данного game_options, то user.first_name обычно неправильно (например, для того же значения game_options, Том играл первым и получил 63, в то время как Джо сыграл на втором месте и получил 100, вместо Джо, Том возвращается с большим счетом Джо).

Я предполагаю, что мне нужно сделать какое-то внутреннее соединение, но не смог понять, так как у меня уже есть внутреннее соединение, которое связывает две таблицы (таблицу пользователей и таблицу игр). Я должен представить, что это дублированный вопрос, но он не мог его найти. Спасибо за любую помощь.

+0

Что должно произойти на галстуках? (т. е. когда есть 2 или более игроков с одинаковым наивысшим счетом для игрового опциона) –

+0

Я бы хотел, чтобы предыдущая запись (у меня есть поле play_id, которое увеличивается для каждой игры), чтобы преобладать на галстуке. –

ответ

1

Один из способов, чтобы показать все привязанные результаты:

SELECT    
    p.words, 
    p.score AS max_score, 
    p.longest, 
    p.game_options, 
    u.first_name, 
    m.cnt AS game_played_count 
FROM played AS p 
    INNER JOIN users AS u 
    ON p.user_id = u.user_id 
    INNER JOIN 
    (SELECT 
      pp.game_options, 
      MAX(pp.score) AS score, 
      COUNT(*) AS cnt 
     FROM played AS pp  
     GROUP BY pp.game_options 
    ) AS m 
    ON m.game_options = p.game_options 
    AND m.score = p.score ; 

С связей решены в соответствии с заранее заданной последовательности:

SELECT    
    p.words, 
    p.score AS max_score, 
    p.longest, 
    p.game_options, 
    u.first_name, 
    dp.cnt AS game_played_count 
FROM 
    (SELECT game_options, 
      COUNT(*) AS cnt 
     FROM played 
     GROUP BY game_options 
    ) AS dp 
    INNER JOIN played AS p 
    ON p.play_id =       -- assuming that `play_id` is the PK 
    (SELECT pi.play_id 
     FROM played AS pi 
     WHERE pi.game_options = dp.game_options 
     ORDER BY pi.score DESC,    -- the predefined 
       pi.play_id ASC    -- order 
     LIMIT 1 
    ) 
    INNER JOIN users AS u 
    ON p.user_id = u.user_id ; 

Индекс по (game_options, score, play_id) помогли бы эффективность - в обоих запросах.

+0

Хммм ... получение непонятной синтаксической ошибки: Неожиданный токен E. –

+0

Хорошо ... вторая версия работает, но ... ничего себе, довольно пугающая для новичка. Я поражен тем, что базовая концепция - это сложная задача. Мне нужно получить достойную книгу SQL, что-то, чтобы мои ноги были мокрыми, не подавляя. В любом случае, спасибо. –

+0

Это намного проще с функцией окна, но, к сожалению, MySQL их не реализовал. Вы можете искать SOHG SO для проблем с наибольшей n-группой для других СУБД (например, SQL-Server, Postgres, Oracle), которые имеют функции окна, чтобы увидеть, как это будет работать. –

Смежные вопросы