0

我使用了这个查询,我认为 mysql 服务器崩溃了。现在无法到达。这是巧合还是我的查询太糟糕了?如果它不好我该如何解决它

处理 400.000 行 2 个表,一个是 scorelisting,另一个是用户

SELECT a.* 
from 
(
    SELECT @curRank := @curRank +1 AS ROW , s.UserId,
       s.AverageScore As Score, u.UserName 
    FROM  scorelisting s, (SELECT @curRank :=0) r, Users u 
    where u.UserId=s.UserId 
    order by AverageScore desc
) a 
where UserId = 95890
4

1 回答 1

2

我不知道我是否过度简化了这一点,但是......如果您正在寻找特定用户在其他人中的位置,我会找出那个人的“平均得分”是什么,然后得到一个 COUNT (*) 所有平均比你想要的更好的记录,然后得到那个人的名字......有意义吗?然后尝试以下。

修订和测试——SQL FIDDLE SQLFiddle 上的示例有 6 个条目,用户 af 和 averageScores 分别为 10-60。该查询选择用户 3 (avgScore),因此 3 (d, e 和 f) 具有更高的平均值 (40, 50, 60),这将用户“c”(id 3) 放在第 4 位。

SELECT 
      u.UserName,
      PreQuery.AverageHigherThanYou +1 as UserRank
   from
      users u,
      ( select
              COUNT(*) as AverageHigherThanYou
           from 
              scoreListing s,
              ( select @MyAvg := s2.AverageScore
                   from scoreListing s2 
                   where s2.UserID = 95890 ) sqlvars
            where
               s.AverageScore > @MyAvg ) PreQuery
    where
       u.userid = 95890

“PreQuery”只是为您的特定用户获取所有这些 LESS 的计数,而不是静态连接到 scoreListing 并放入单个列值中。

然后逗号用户表(旧的 ANSI,无连接条件)将始终返回一条记录...然后,仅在 USER 表上应用 WHERE 子句,以获取他们的姓名信息。

现在,如果您想要有多少是较高、相同或较低的平均值,您可以调整查询,例如

  ( SELECT 
          sum( if( s.averageScore < s2.averageScore, 1, 0 )) as LowerAverageThanYou,
          sum( if( s.averageScore = s2.averageScore, 1, 0 )) as SameAverageAsYou,
          sum( if( s.averageScore > s2.averageScore, 1, 0 )) as HigherAverageThanYou
       from 
          scoreListing s
             join scoreListing s2
                ON s2.UserID = 95890 ) PreQuery,

你显然必须等到你的机器被释放后再试一次。

I would also have two indexes on the scoreListing table. One on just the ID to jump to UserID = 95890 record for comparing that person's average, and another on the averageScore, so if you did HIGHER THAN only, your WHERE clause would only have to scan through those records and not the entire 400,000 records.

于 2012-11-26T01:22:24.337 回答