SQL查詢中,根據列A分組,分組後針對列B執行統計函數,是一件經常使用也很重要功能,如select T.a, max(T.b) from T order by T.a asc, T.b desc group by T.a
select T.a, count(T.b) from T order by T.a asc, T.b desc group by T.a
一直這樣寫SQL,直到有一天,一個作股票的朋友(非IT人事)和我聊天,說他本身用Python整了點數據,想分析下每一個版塊成交量前三的股票,問我知不知道怎麼用SQL查出來(這是一個分組排名取若干首級的需求)。老實說,這個問題很常見,可是腦子剎那間有點懵逼,回來的路上一直想這個問題,若干年前用SQLServer時,有個分組方法ROW_NUMBER() OVER(),貌似能夠實現這個分組排名功能。sql
語法格式:row_number() over(partition by 分組列 order by 排序列 desc)ide
與是網上搜了下MySQL 的實現,果真一堆朋友記錄過。參照了一篇CSDN微博「Mysql實現ROW_NUMBER() OVER()」 的內容,將實現過程記錄以下。函數
先看下錶結構:
view_market_trade_amt有三列,第一列是指數,第二列是股票代碼,第三列是成交量。
需求是將各個指數板塊的成交前三的股票查出來。
.net
實現MySQL rownum() over()以前,須要先了解下這種實現方式的思想:根據分組列排序後,定義rownum標記,rownum的標記隨着分組列變化而變化,分組列值相同時,rownum不變,最後每一個分組列造成一個rownum序列,以後根據rownum序列篩選排名。code
select v.stockCode,v.tradeIndex,v.amount, if(@grpvar=v.tradeIndex,@rownum:=@rownum+1,@rownum:=1) as rownum, @grpvar:=v.tradeIndex from (select stockCode,tradeIndex,amount from view_market_trade_amt order by tradeIndex asc ,amount desc) v , (select @grpvar := null ,@rownum:=0) vardef
vardef是定義分組變量和rownum變量,分別默認賦值null和0;
grpvar賦值tradexIndex,同時判斷當前記錄的tradeIndex和該變量是否相等,若是相等則rownum+1,不然從1開始賦值。
查詢結果:
blog
能夠看到,不一樣的tradeIndex,對應rownum序列都是獨立。排序
select tradeIndex, stockCode, amount from ( select v.stockCode,v.tradeIndex,v.amount, if(@grpvar=v.tradeIndex,@rownum:=@rownum+1,@rownum:=1) as rownum, @grpvar:=v.tradeIndex from (select stockCode,tradeIndex,amount from view_market_trade_amt order by tradeIndex asc ,amount desc) v , (select @grpvar := null ,@rownum:=0) vardef ) as result where result.rownum<=3