запрашивание рейтинга пользователя в таблицах «один ко многим» - PullRequest
0 голосов
/ 24 июня 2010

Я пытаюсь написать запрос, чтобы найти рейтинг в играх пользователя.Мне нужно взять идентификатор пользователя, а затем вернуть относительный рейтинг этого пользователя в оценки других пользователей.Есть пользователь и игровой стол.В игровой таблице есть поле userId с отношением «один ко многим».

Пример таблицы:

пользователи:
id freebee
1 10
2 13

игры:
userId счет
1 15
1 20
2 10
1 15

Передача $ id 1 в эту функцию должна вернуть значение 1, поскольку пользователь 1 в настоящее время имеет наивысший балл.Аналогично, пользователь 2 вернул бы 2.

В настоящее время это то, что у меня есть:

SELECT outerU.id, (

SELECT COUNT( * )  
FROM users userI, games gameI  
WHERE userI.id = gameI.userId  
AND userO.id = gameO.userId  
AND (  
   userI.freebee + SUM(gameI.score)  
   ) >= ( userO.freebee + SUM(gameO.score) )  
) AS rank  
FROM users userO,  
games gameO  
WHERE id = $id

, что приводит к ошибке «недопустимое использование групповой функции».Есть идеи?

Ответы [ 5 ]

1 голос
/ 24 июня 2010
SELECT u.id,total_score,
 ( SELECT COUNT(*) FROM
    (SELECT u1.id, (IFNULL(u1.freebee,0)+ IFNULL(SUM(score),0)) as total_score
     FROM users u1
     LEFT JOIN games g ON (g.userId = u1.id)
     GROUP BY u1.id
    )x1
   WHERE x1.total_score > x.total_score
 )+1 as rank,

( SELECT COUNT(DISTINCT total_score) FROM
    (SELECT u1.id, (IFNULL(u1.freebee,0)+ IFNULL(SUM(score),0)) as total_score
     FROM users u1
     LEFT JOIN games g ON (g.userId_Id = u1.id)
     GROUP BY u1.id
    )x1
   WHERE x1.total_score > x.total_score
 )+1 as dns_rank

 FROM users u

 LEFT JOIN
  ( SELECT u1.id, (IFNULL(u1.freebee,0)+ IFNULL(SUM(score),0)) as total_score
    FROM users u1
    LEFT JOIN games g ON (g.userId = u1.id)
    GROUP BY u1.id
  )x ON (x.id = u.id)

rank - (обычный ранг, например, 1,2,2,4,5), dns_rank - плотный ранг (1,2,2,3,4)Колонка total_score - только для отладки ...

1 голос
/ 24 июня 2010

Запросу не нравится ссылка на внешнюю таблицу в функции Sum SUM(gameO.score) в коррелированном подзапросе.Во-вторых, прекратите использовать формат запятой для объединений.Вместо этого используйте синтаксис ANSI JOIN.Например, в своем внешнем запросе вы действительно хотели использовать перекрестное соединение?Вот как вы написали и как я представил это в приведенном ниже решении, но я сомневаюсь, что это то, что вы хотите.

РЕДАКТИРОВАТЬ

Я изменил свой запрос с учетом вашей новой информации.

Select U.id, U.freebee, GameRanks.Score, GameRanks.Rank
From users As U
    Join    (
            Select G.userid, G.score
                , (
                    Select Count(*)
                    From Games As G2
                    Where G2.userid = G.userid
                        And G2.Score > G.Score
                    ) + 1 As Rank
            From Games As G
            ) As GameRanks
        On GameRanks.userid = U.id
Where U.id =1
0 голосов
/ 21 октября 2010
0 голосов
/ 24 июня 2010

Вот «упрощенная» версия для расчета ранга только по таблице «игры».Для расчета рейтинга только для конкретной игры вам нужно добавить дополнительные объединения.

SELECT COUNT(*) + 1 AS rank
FROM   (SELECT userid,
               SUM(score) AS total
        FROM   games
        GROUP  BY userid
        ORDER  BY total DESC) AS gamescore
WHERE  gamescore.total > (SELECT SUM(score)
                          FROM   games
                          WHERE  userid = 1)  

Это основано на идее, что ranking == number of players with bigger score + 1

0 голосов
/ 24 июня 2010

Я не человек MySQL, но я считаю, что обычный способ ранжирования в нем - использовать переменную в вашем выражении SQL. Нечто подобное ниже (не проверено):

SELECT
    SQ.user_id,
    @rank:=@rank + 1 AS rank
FROM
(
    SELECT
        U.user_id,
        U.freebee + SUM(COALESCE(G.score, 0)) AS total_score
    FROM
        Users U
    LEFT OUTER JOIN Games G ON
        G.user_id = U.user_id
) SQ
ORDER BY
    SQ.total_score DESC

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

...