mysql中這樣解決數據排序和分組排序


為大家熟知的關系型數據庫有mysql、SQLServer、oracle、DB2等。它們的sql語句其實是有細微的差別的,不要想着有些語句在SQLServer上可以用就可以在mysql上使用。今天老韓就來講一下其中的一個知識點,mysql中如何排名。

SQLServer和oracle中有row_num函數,可以對數據庫中信息進行排名,但是mysql中卻沒有這個函數,那么在mysql中如何解決這個問題呢,下面老韓分為兩塊來講解這個問題。

一、直接排序編號;

老韓想對student學生表中的學生按照score來進行排名,有些讀者朋友說了,直接用order by一下不就完了,這樣是按照成績排名了,但是並沒有編號,所以僅僅使用order by相當於需求實現了一部分,而且是很少的一部分,廢話不多說直接上SQL語句:

set @nub:=0;

select (@nub:=@nub+1) as 排名,a.* from student a order by score;

執行結果:可以看到已經實現了需求,既排序了,又有了排名字段,咱們來分析一下SQL語句,set是賦值,還有一個賦值的關鍵字是select,但是使用select時候就不能直接將上面SQL語句中的set直接替換為select,因為select必須和select語句結合來使用,必須寫成:select @nub:=@nub+1 as 排名,b.* from (select * from student ) b, (select @nub:=0) c order by score

“@”是聲明變量的意思,除了“@”還有“@@”,兩個@符號表示是全局變量,一個@符號表示局部變量,mysql中也可以使用declare聲明變量,但是在這不可以使用,后面存儲過程章節,老韓會講,就跟Java中的new關鍵字一樣,“:=”表示賦值,這個地方等同於“=”,由於“:=”比“=”使用范圍廣泛,統一使用“:=”即可,@nub:=@nub+1表示@nub先+1再賦值給@nub,這個地方是前面老韓講過的虛擬列,這里不多做贅述。

二、分組后再排序編號;

直接上SQL語句,老韓再針對SQL語句進行分析,SQL語句:

select

@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名,c.*,@classnoCopy:=c.classno

from

(select b.* from (select distinct classno from student order by classno)a left join student b on a.classno = b.classno) c ,(select @nub:=0, @classnoCopy:=0 )d

查詢結果為:如下圖所示,可以看到實現了我們的需求。

先對學生進行分組再通過score來排名,老韓針對上面的sql語句來進行一個分析,分析一個sql語句的時候先從內往外分析,因為執行的時候也是從內而外,有人會問你為啥知道,如果內部不執行,外部如何查數據,肯定是內部先出來數據之后,外部才能去查。

最下面的別名為d的數據集,這個地方前面已經講過,聲明兩個變量並賦值。

別名為c的數據集,這里面有個關鍵字distinct,表示去重,實際上不寫也沒問題但是老韓為了更明顯就寫了,表示取student表中所有的班級編號並去重,加上left join表示以班級為主表來進行數據填充,因為老韓又加了order by classno表示升序排列,那么所有的信息都會以這個順序去匹配,效果如下圖所示;

加上left join之后的效果如下圖所示,如果不能理解為什么是這種效果可以查看前面的左連接、右連接章節,其實這個地方完全可以寫成select username,classno,score from student order by classno,這里是趕巧了可以直接使用order by,如果是字符串就不好說了。

最關鍵的地方來了,@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名,c.*,@classnoCopy:=c.classno這兩句代碼如何理解呢?我們要明確一點,sql執行就想Java程序main方法中代碼執行一樣,從上到下去執行,先執行@nub:=(case when @classnoCopy=classno then @nub+1 else 1 end ) as 排名。

這里面有個case when 語句,讀者朋友不要懵逼,這個東西其實我們前面學過的,它表示當classnoCopy=classno返回true的時候@nub=@nub+1,else就是返回false,@nub=1,最后以end結尾,表示語句結束,是不是跟三元運算非常相似啊,其實mysql中也有三元運算但是寫法跟Java中不一樣,所以上面的語句可以寫成這樣:@nub:=if(@classnoCopy=classno,(@nub+1),1),if(),瓜號內有三個變量,第一個變量就是表達式,返回一個boolean類型,后面跟兩個值,如果是true就返回第一個值,如果false就返回第二個值。

sql語句執行是從這一句開始執行的,可以看到,剛開始@classnoCopy是0,很明顯跟班級編號不一樣,那么這個時候排名等於1,開始執行下面的語句,下面的語句是賦值,將classno賦值給@classnoCopy,sql語句是一行一行對結果集進行掃描的,到第二行的時候,@classnoCopy=classno很明顯是成立的,所以排名會加1變成2,掃描第三行的時候@classnoCopy=classno不成立了,因為這個時候@classnoCopy是1,classno是2,排名又變成了1,循環執行語句就得到需要的結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM