如果列值出现一次,MySQL会重新排列/重新排序行位置

时间:2015-03-02 12:15:50

标签: mysql sql

在如下例所示的表格中

+--------+-------------------+-----------+
| ID     | Name              |  Score    |
+--------+-------------------+-----------+
| 1      | John              | 80        |
| 2      | John              | 75        |
| 3      | Daniel            | 70        |
| 4      | Lisa              | 60        |
| 5      | Joe               | 74        |
+--------+-------------------+-----------+

我想选择名称并根据他们的分数定位它们,但仍然要确保如果同一名称出现两次,那么就可以将其推下(这样在上面的例子中John就不会出现两次了(例如,当我检索它时,它应该采用以下格式:

+--------+-------------------+-----------+
| ID     | Name              |  Score    |
+--------+-------------------+-----------+
| 1      | John              | 80        |
| 2      | Joe               | 74        |
| 3      | Daniel            | 70        |
| 4      | Lisa              | 60        |
| 5      | John              | 75        |
+--------+-------------------+-----------+

如果可以进行这样的查询,那么我们甚至可以控制推动行的下方多远?

2 个答案:

答案 0 :(得分:2)

试试这个:

SELECT  @RN := @RN + 1 AS ID,Name,Score FROM 
(SELECT T1.Name, T1.Score, count(*) as RN1 
 FROM TableName T1
 JOIN TableName T2 ON T1.Name = T2.Name AND T1.Score <= T2.Score
 GROUP BY T1.Name, T1.Score) TempTable,(SELECT @RN := 0) R
ORDER BY RN1, Score DESC

结果:

ID  NAME    SCORE
1   John    80
2   Joe     74
3   Daniel  70
4   Lisa    60
5   John    75

SQL Fiddle中的示例结果。

<强>解释

如果执行内部查询,您将获得按分数desc排序的记录以及列RN1为John为2,其他为1。它基本上是一个排名系统。然后我们将根据RN1列的结果进行排序。因此,您将获得名称和分数的结果。

外部查询用于添加ID列(实际上是行号列)。

答案 1 :(得分:1)

我倾向于聚合数据并计算每个名称的行数和最大分数。然后将此信息用于order by

select t.*
from table t join
     (select name, max(score) as maxs, count(*) as cnt
      from table t
      group by name
     ) tt
     on t.name = tt.name
order by (case when t.score = t.maxscore then 1 else 2 end),
         score desc;

如果最高得分没有重复,这应该有效 - 正如您的实际数据一样。解决此问题的一种方法是使用id代替:

select t.id, t.name, t.score
from (select t.*,
             (select t2.id
              from table tt
              where tt.name = t.name
              order by score desc
              limit 1
             ) as maxscore_id
      from table t
     ) t
order by (id = maxscore_id) desc, score desc;