当前位置: 首页 > 知识库问答 >
问题:

MySQL ORDER BY多列ASC和DESC

崔宜修
2023-03-14

我有2个MYSQL表,用户和分数。详细信息:

  • 用户表:

  • 得分表:

我的目的是获得20个用户列表,这些用户具有点域排序DESC(降序)和平均时间域排序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

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

提前谢谢!

共有3个答案

微生令雪
2023-03-14

@德拉普是个天才。我一直不明白他是如何编写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而不是user@变量,可以得到相同的结果。

萧永长
2023-03-14

我想你错过了对餐桌关系的理解...

用户:分数=1:*

只是加入不是一个解决方案。

这是你的意图吗?

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 point, asc获取每个用户的平均值和平均值avg_time)avg_time

如果你想得到每个分数的排名?使用左外连接

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
栾和风
2023-03-14

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

现在是查询。如果上面的语句是准确的,你需要从获得每个人的最佳点/平均时间开始,并为该条目分配一个“排名”。这很容易使用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
 类似资料:
  • 问题内容: 在MS SQL Server 2008 R2中编写存储过程,我想避免使用DSQL … 我希望有条件的排序方法(ASC或DESC)。 现在,对于一个数字列,我将只使用一个case语句并取反该值以模拟ASC或DESC …即: 用alpha列执行此操作的合适方法是什么? 编辑:我想到了一个聪明的方法,但似乎效率很低…我可以使用自动编号将有序的alpha列插入到临时表中,然后使用上述方法按自动

  • 问题内容: 我需要按日期/时间字段(例如)升序对PostgreSQL表进行排序last_updated。 但是,该字段允许为空或空,我想与空记录之前,非空。 这可能吗? 问题答案: 为该ORDER BY子句提供了关键字,以完全满足该需求: 一个典型的用例是使用降序排序(DESC),它会生成默认的升序(ASC)的完整反转,首先是空值。通常不理想-因此,将null值保持在最后: 要支持带有索引的查询,

  • 问题内容: 桌子: 的PHP HTML结果: 任何人都注意到桌上的结果。时代是不正确的顺序? 我改变了另一种方式与ASC / DESC,仍然显示最后一个id_timeslot的时间吗? 预期结果: 问题答案: 您正在对记录进行分组,因此每种情况下您只会看到最后一次。 尝试使用

  • 问题内容: 我了解我可以按如下顺序在sql查询中按顺序使用变量: 但是我也该如何在asc和desc部分中使用变量? 问题答案: 没有每个选项,它的子句例如:

  • 问题内容: 我使用以下SP来对新闻文章列表进行分页。您可能会猜到,是要返回的行数,是从中选择行的索引(按内部查询排序),指示要排序的列,并指示是否对一个方向或另一个方向进行排序。在添加参数之前,我的原始查询在 这里。 现在,实际上没有任何问题,但是参数不起作用。如果提供1作为参数,它将为我提供与提供2作为该参数完全相同的结果。 问题答案: 行号不会在每一行上求值,但是case语句是有效的,因此无论

  • 我有一张日期表 我想按时间顺序点菜。我发现另一个线程推荐使用: 但输出不能正确地将最新的排序为最旧的。