MySQL ORDER BY多列ASC和DESC

时间:2012-12-04 01:49:03

标签: mysql sql-order-by multiple-columns

我有2个MYSQL表,用户得分。详情:

  • 用户表:

enter image description here

  • 得分表:

enter image description here

我的目的是获得20个用户列表 point 字段排序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

结果是:

enter image description here

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

我想要的结果是:

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

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

提前致谢!

4 个答案:

答案 0 :(得分:25)

好的,我认为我理解你现在想要的东西,让我在查询之前澄清确认。您希望每个用户拥有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

Results as handled by SQLFiddle

注意,由于获得答案所需的内联@variables,每行末尾有两个额外的列。这些只是“遗留下来”,可以在您尝试的任何实际输出演示文稿中被忽略...或者,您可以将整个事物包装在一个更多级别上,以获得您想要的几个列

select 
      PQ.UserName,
      PQ.Point,
      PQ.Avg_Time
   from
      ( entire query above pasted here ) as PQ

答案 1 :(得分:1)

我想你错过了关于表格的关系..

  

用户:得分= 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

答案 2 :(得分: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会产生相同的结果。

答案 3 :(得分:0)

默认按pk id排序,所以结果为 用户名点avg_time
demo123 100 90 ---> id = 4
demo123456 100 100 ---> id = 7
demo 90 120 ---> id = 1