Оптимизировать запрос для создания рейтинга в MS SQL Server - PullRequest
1 голос
/ 07 июня 2019

Я создаю приложение, где пользователи делают тренировки.Они передают свои результаты через приложение, и эти результаты сохраняются в базе данных SQL Server.Результаты сохраняются таким образом в таблице SQL Server:

SQL Server table

Я хочу написать запрос для создания рейтинга, основанного на лучшем балле каждогопользователь.Это то, что я до сих пор:

SELECT id, 
       workout_id, 
       level_id, 
       a.user_id, 
       total_time, 
       score, 
       datetime_added
FROM nodefit_rankings_fitness as a INNER JOIN
    (
     SELECT user_id, 
            MAX(score) AS MAXSCORE 
     FROM nodefit_rankings_fitness 
     GROUP BY user_id
    ) AS lookup
ON  lookup.user_id = a.user_id
    AND 
    lookup.MAXSCORE  =  a.score
ORDER BY score DESC, 
         datetime_added DESC

Это генерирует этот рейтинг:

SQL Server

Проблема в том, что если пользовательдостиг одного и того же максимального балла несколько раз, он будет появляться несколько раз в рейтинге.Запрос должен быть скорректирован таким образом, чтобы, когда пользователь несколько раз получал один и тот же максимальный балл, в рейтинге отображался только результат последней попытки (на основе столбца datetime_added).

К сожалению, яне могу найти решение сам.Помощь, безусловно, ценится.

Ответы [ 2 ]

1 голос
/ 07 июня 2019

Если вы заботитесь о производительности, вам также следует попробовать коррелированный подзапрос:

SELECT id, workout_id, level_id, a.user_id, total_time, score, datetime_added
FROM nodefit_rankings_fitness nrf
WHERE nrf.id = (SELECT TOP (1) nrf2.id
                FROM nodefit_rankings_fitness nrf2
                WHERE nrf2.user_id = nrf.user_id
                ORDER BY nrf2.score DESC
               )
ORDER BY score DESC, datetime_added DESC;

В частности, для этого может быть использован индекс nodefit_rankings_fitness(user_id, score desc, id).

1 голос
/ 07 июня 2019

Оконные функции делают вещи такими простыми. Что-то вроде:

SELECT id, workout_id, level_id, user_id, total_time, score, datetime_added
FROM (SELECT *, row_number() OVER (PARTITION BY user_id ORDER BY score DESC, datetime_added DESC) AS rn
      FROM nodefit_rankings_fitness) AS a
WHERE rn = 1
ORDER BY score DESC, datetime_added DESC;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...