在如下例所示的表格中
+--------+-------------------+-----------+
| 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 |
+--------+-------------------+-----------+
如果可以进行这样的查询,那么我们甚至可以控制推动行的下方多远?
答案 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;