33

我有 2 个 MYSQL 表,用户分数。细节:

  • 用户表:

在此处输入图像描述

  • 成绩表:

在此处输入图像描述

我的意图是让 20 个用户列表具有字段排序 DESC(降序)结合avg_time字段排序 ASC(升序)。我使用查询:

SELECT users.username, scores.point, scores.avg_time
FROM scores, users
WHERE scores.user_id = users.id
GROUP BY users.username
ORDER BY scores.point DESC, scores.avg_time
LIMIT 0, 20

结果是:

在此处输入图像描述

结果是错误的,因为第一行恰好是 point = 100 和 avg_time = 60。

我想要的结果是:

username    point    avg_time
demo123      100        60
demo123456   100       100
demo         90        120

我用不同的查询尝试了很多次,但结果仍然是错误的。你能给我一些解决方案吗?

提前致谢!

4

4 回答 4

29

好的,我想我现在明白你想要什么了,让我在询问前澄清一下。您希望每个用户有 1 条记录。对于每个用户,您都需要他们的 BEST POINTS 得分记录。在每位用户的最佳积分中,您想要平均时间最长的积分。一旦您拥有所有用户的“最佳”值,您希望最终结果首先按最佳点排序......几乎就像比赛的排名一样。

所以现在查询。如果上述陈述是准确的,您需要从获得每人的最佳分数/平均时间开始,并为该条目分配一个“排名”。这很容易使用 MySQL @ 变量完成。然后,只需包含一个 HAVING 子句,只保留每个人的排名为 1 的记录。最后应用最佳点和最短平均时间的顺序。

select
      U.UserName,
      PreSortedPerUser.Point,
      PreSortedPerUser.Avg_Time,
      @UserRank := if( @lastUserID = PreSortedPerUser.User_ID, @UserRank +1, 1 ) FinalRank,
      @lastUserID := PreSortedPerUser.User_ID
   from
      ( select
              S.user_id,
              S.point,
              S.avg_time
           from
              Scores S
           order by
              S.user_id,
              S.point DESC,
              S.Avg_Time ) PreSortedPerUser
         JOIN Users U
            on PreSortedPerUser.user_ID = U.ID,
      ( select @lastUserID := 0,
               @UserRank := 0 ) sqlvars 
   having
      FinalRank = 1
   order by
      Point Desc,
      Avg_Time

SQLFiddle 处理的结果

请注意,由于获得答案需要内联 @variables,因此每行末尾有两个额外的列。这些只是“剩余的”,可以在您尝试执行的任何实际输出演示中被忽略...或者,您可以将整个内容包装到一个更高的级别,以获得您想要的几列

select 
      PQ.UserName,
      PQ.Point,
      PQ.Avg_Time
   from
      ( entire query above pasted here ) as PQ
于 2012-12-04T11:39:11.370 回答
3

我想你想念关于表关系的理解..

用户:分数 = 1:*

只是join不是一个解决方案。

这是你的意图吗?

SELECT users.username, avg(scores.point), avg(scores.avg_time)
FROM scores, users
WHERE scores.user_id = users.id
GROUP BY users.username
ORDER BY avg(scores.point) DESC, avg(scores.avg_time)
LIMIT 0, 20

(此查询通过 desc 点获取每个用户的平均点和平均 avg_time,asc)avg_time

如果你想得到每个分数排名?采用left outer join

SELECT users.username, scores.point, scores.avg_time
FROM scores left outer join users on scores.user_id = users.id
ORDER BY scores.point DESC, scores.avg_time
LIMIT 0, 20
于 2012-12-04T01:56:05.867 回答
1

@DRapp 是个天才。我一直不明白他是如何编写 SQL 的,所以我尝试按照自己的理解编写代码。


    SELECT 
      f.username,
      f.point,
      f.avg_time
    FROM
      (
      SELECT
        userscores.username,
        userscores.point,
        userscores.avg_time
      FROM
        (
        SELECT
          users.username,
          scores.point,
          scores.avg_time
        FROM
          scores
        JOIN users
        ON scores.user_id = users.id
        ORDER BY scores.point DESC
        ) userscores
      ORDER BY
        point DESC,
        avg_time
      ) f
    GROUP BY f.username
    ORDER BY point DESC

通过使用 GROUP BY 而不是用户 @variables,它会产生相同的结果。

于 2014-07-02T15:19:41.890 回答
0

默认按照pk id排序,所以结果
username point avg_time
demo123 100 90 ---> id = 4
demo123456 100 100 ---> id = 7
demo 90 120 ---> id = 1

于 2012-12-04T08:36:04.170 回答