0

我正在尝试在 Mysql 中执行查询以获取用户的所有时间排名。对于当月的排名,我设法通过以下要求做到了:

SELECT MAX(x.rank) AS rank
  FROM (SELECT 
               t.id_user,
               @rownum := @rownum + 1 AS rank
          FROM screengame_points t
          JOIN (SELECT @rownum := 0) r
          WHERE month = $month
      ORDER BY t.points DESC) x
 WHERE x.id_user = 4

一直以来,我都需要计算所有点的总和,所以我尝试了:

SELECT MAX(x.rank) AS rank
  FROM (SELECT 
               t.id_user,
               @rownum := @rownum + 1 AS rank
          FROM screengame_points t
          JOIN (SELECT @rownum := 0) r
    GROUP BY id_user
      ORDER BY sum(t.points) DESC) x
 WHERE x.id_user = 4

(注意“id_user 分组”和“sum(t.points)”)。

但它不起作用。我认为第二个请求中的排名结果是从一个月内得分最高的一个到最差的一个。它不是整个月所有点的总和。

我怎么能做到?

4

2 回答 2

1

我怀疑问题是ORDER BY在这两种情况下都被优化掉了。在第一种情况下,您可能只是幸运。

MySQL 文档确实说ORDER BY在子查询中是允许的。然而,这里有一个关于UNION.

但是,对单个 SELECT 语句使用 ORDER BY 并不意味着行在最终结果中出现的顺序,因为默认情况下 UNION 会产生一组无序的行。因此,在此上下文中使用 ORDER BY 通常与 LIMIT 结合使用,因此它用于确定要为 SELECT 检索的所选行的子集,即使它不一定影响这些行在最终的 UNION 结果。如果 ORDER BY 在 SELECT 中出现时没有 LIMIT,则它会被优化掉,因为无论如何它都没有效果。

我强调这是关于UNION条款的;关于简单的子查询,我找不到任何东西。但是,ORDER BY在标准 SQL 中是不允许的,除了最外层。原因很简单。. . 表和子查询是无序的。

您可以通过LIMIT在子查询中包含子句来欺骗 MySQL。放入足够大的数量以获取所有用户(尽管理论上可以优化掉)。

您有两个其他选项来获取此信息。如果您的表不是太大,您可以使用自连接来获取排名信息。您还可以插入具有自动增量列的临时表;我认为order by将在那里工作。(而且我不考虑切换数据库,因为几乎所有其他数据库都支持该rank功能。)

于 2012-11-10T17:30:38.507 回答
0

我找到了一个解决方案,但我认为查询我的执行速度很慢,有很多记录!

SELECT WrappedQuery.rank 
FROM (SELECT @rownum := @rownum +1 as rank, id_user
      FROM ( select @rownum := 0 ) sqlvars,
           (SELECT  t.id_user
            FROM screengame_points t
        GROUP BY id_user
            ORDER BY sum(t.points) DESC
        ) x 
     ) WrappedQuery
WHERE id_user = 4
于 2012-11-11T10:41:23.863 回答