查询用户在一对多表中的排名

时间:2010-06-24 15:13:39

标签: mysql sql mysql-error-1111

我正在尝试编写查询以查找用户游戏的分数排名。我需要它来获取用户ID,然后将该用户的相对排名返回给其他用户的分数。有一个用户和一个游戏桌。游戏表具有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 个答案:

答案 0 :(得分:1)

查询不喜欢相关子查询中Sum函数SUM(gameO.score)中外部表的引用。其次,停止使用逗号格式进行连接。而是使用JOIN的ANSI语法。例如,在您的外部查询中,您真的是要使用交叉连接吗?这就是你如何编写以及我如何在下面的解决方案中表示它,但我怀疑这是你想要的。

修改

我根据您的新信息调整了我的查询。

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

答案 1 :(得分:1)

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 - 仅用于调试...

答案 2 :(得分:0)

我不是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

您可以将其用作子查询来获取单个用户的排名,尽管性能方面可能不是最佳路径。

答案 3 :(得分:0)

这是用于仅根据“游戏”表计算排名的“简化”版本。要计算特定游戏的排名,只需添加其他联接。

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

的想法

答案 4 :(得分:0)