首先 我們新建一個表,表信息如下:
CREATE TABLE `report` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`score` int(4) DEFAULT NULL COMMENT '分數',
`user_name` varchar(255) DEFAULT NULL COMMENT '姓名',
`exam_time` time DEFAULT NULL COMMENT '考試時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='成績表';
假如是一般的排序 ,那我們直接按照分數降序排序,SELECT * FROM report ORDER BY score DESC;
查出來一個list,list的索引就當做它的排名(當然是索引+1)。
或者直接用sql,在sql裏標明排名序號:
SELECT
@rownum := @rownum + 1 AS rownum,
r.*
FROM
report r,
(SELECT @rownum := 0) b
ORDER BY
score DESC
上面的@方式是mysql定義變量的方式,用:=進行賦值。
這兩種方法都是簡單的進行降序排序,然後加上序號,顯然很low,也不符合需求。
一般的成績單呢,應該是分數相同的,排名一致,以此類推。所以,我們給出三種查詢方式:
方式一:藉助建立僞表,比較大小並排序
SELECT
count(b.user_name) + 1 AS rk,
a.*
FROM
report a
LEFT JOIN report b ON a.score < b.score
GROUP BY
a.user_name
ORDER BY
count(b.user_name) + 1;
方式二: 藉助於if函數判斷以及自定義方式
SELECT
@rownum:=@rownum+1 AS rownum,
if(@score=A.score,@rank,@rank:=@rownum)as rank,
@score:=A.score,
A.user_name,A.score,A.exam_time
FROM
(SELECT * FROM report ORDER BY score DESC) A,
(SELECT @rank:=0,@rownum:=0,@score:=null)B
方式三:藉助case when函數判斷:
select
count(case when a.score < b.score then b.user_name else null end)+1 as rank,
a.user_name,a.score,a.exam_time
from report a
left join report b
on 1=1
group by a.user_name,a.score,a.exam_time
order by rank
以上三種方式的結果大概意思是這樣:如下圖
到此 成績單的排序,就基本滿足普通的需求了。
由於博主本人又遇到了新需求,對於一些小測驗啥的,要求,分數一樣的,按時間長短排序,分數時間都一樣,排名形同。
這樣的話,其實就是對以上三種方法再加些判斷條件。
對於第一種的話,就稍微複雜一點。如下:
方式A:
select a.rk+count(b.user_name) as rk,a.user_name,a.score,a.exam_time
from
(
select a.user_name,a.exam_time,a.score,count(b.user_name)+1 as rk
from report a
left join report b on a.score < b.score
group by a.user_name
order by count(b.user_name)+1
)a
left join
(
select a.user_name,a.exam_time,a.score,count(b.user_name)+1 as rk
from report a
left join report b on a.score < b.score
group by a.user_name
order by count(b.user_name)+1
)b
on a.rk = b.rk
and a.exam_time > b.exam_time
group by a.user_name
order by a.rk+count(b.user_name)
相當於是在第一種方式的基礎上,套了一大層當做表,然後再做判斷,當然對於第一種應該還有更優化的方法,歡迎大家來寫出自己的想法。結果如下圖:
這樣的寫法,乍一看,代碼有點多,那麼對於用函數的,怎麼查詢呢?
方式B:
SELECT
@rownum:=@rownum+1 AS rownum,
if((@score=A.score && @exam_time=A.exam_time),@rank,@rank:=@rownum)as rank,
@score:=A.score,@exam_time:=A.exam_time,
A.user_name
FROM
(
SELECT * FROM report ORDER BY score DESC,exam_time ASC
) A,
(SELECT @rank:=0,@rownum:=0,@score:=NULL,@exam_time:=NULL)B
這個方法的結果如下圖:
那麼 ,假如想要查詢某個人的信息以及排名呢,所有人的都查出來了,查某個人的,就加個判斷條件啦
SELECT C.*
FROM
(
SELECT
@rownum:=@rownum+1 AS rownum,
if(@score=A.score,@rank,@rank:=@rownum)as rank,
@score:=A.score,
A.user_name,A.score,A.exam_time
FROM
(SELECT * FROM report ORDER BY score DESC) A,
(SELECT @rank:=0,@rownum:=0,@score:=null)B
) C WHERE C.user_name ='lisi'
以上。
歡迎大家評論,有更好的方法的話,大家可以相互交流下。