今天遇到一個MYSQL排序的問題,要求按某列進行分組,組內進行排序.
百度一下發現MYSQL不支持row_number(),rank()等函數.
采用的辦法如下,我們首先創建一個測試表:
--創建表 create table Rank_test(ID int,SCORE int,grp int) --插入數據 insert into Rank_test values(1 , 28,1); insert into Rank_test values(2 , 33,1); insert into Rank_test values(3 , 33,1); insert into Rank_test values(4 , 89,1); insert into Rank_test values(5 , 99,1); insert into Rank_test values(6 , 68,1); insert into Rank_test values(7 , 68,1); insert into Rank_test values(8 , 78,1); insert into Rank_test values(9 , 88,1); insert into Rank_test values(10, 90 ,1); insert into Rank_test values(11, 28,2); insert into Rank_test values(12, 33,2); insert into Rank_test values(13, 33,2); insert into Rank_test values(14, 89,2); insert into Rank_test values(15, 99,2); insert into Rank_test values(16, 68,2); insert into Rank_test values(17, 68,2); insert into Rank_test values(18, 78,2); insert into Rank_test values(19, 88,2); insert into Rank_test values(20, 90 ,2);
分組排序的SQL代碼:
SELECT id, score, rank FROM (SELECT tmp.id, tmp.score, @rank := (case when @Grp = grp then @rank + 1 else 1 end) AS rank , @Grp:=grp as grp2 FROM (SELECT id, score, grp FROM rank_test) tmp, (SELECT @rank := 0,@grp:=0) a order by grp,score desc) RESULT ;
結果如下:
測試結果OK,但重點是套用到我們的SQL中后,排序結果完全不是我們預期中的,而且沒有找到規律.
經過幾次嘗試,最后重新改寫了SQL代碼,終於成功了.
原因是套用下面這段代碼時,我們是用了幾張表進行關聯(inner join ),最后將inner join 的表全部改為where 語句中的子句,結果滿足我們的預期.
(SELECT id, score, grp FROM rank_test) tmp,
所以建議在這里的代碼盡量使用單表,不要多張表關聯
附上修改前后的代碼:(紅色部分是修改前,綠色部分是修改后)
select * from ( select evtdate ,stkabb,chng,PCTCSHG,cshg,SHHNAME ,@rank := (case when @SHHNAME=SHHNAME then @rank + 1 else 1 end) AS rank ,@SHHNAME:=SHHNAME from ( select tt.SHHNAME -- 股東名稱 ,s.evtdate -- 變動日期 ,r.stkabb -- 變動股票名稱 ,ifnull(s.RLDSHG,s.cshg-s.SHGBCH)/10000 as chng -- 變動股數(萬股) ,s.cshg/10000 as cshg-- 變動后持股(萬股) ,s.PCTCSHG -- 變動后持股比例% from pgenius.hk_stkcode r inner join pgenius.HK_SAKCHMJSHH s on r.comunic = s.comunic inner join (select distinct b.SHHNAME from pgenius.hk_stkcode a inner join pgenius.HK_SAKCHMJSHH b on a.comunic = b.comunic and b.evtdate = (select max(evtdate) from pgenius.HK_SAKCHMJSHH where comunic = b.comunic and SHHNAME = b.SHHNAME and NTUREFCINTRTS = b.NTUREFCINTRTS) where a.lssturefc = 1 and b.cshg > 0 and a.stkcode = '00001' ) tt on s.SHHNAME = tt.SHHNAME ) t1, (SELECT @rank := 0,@SHHNAME:='') t2 order by SHHNAME,evtdate desc,stkabb ) t
select t.* , o.stkabb from ( select t1.* ,@rank := (case when @SHHNAME=SHHNAME then @rank + 1 else 1 end) AS rank ,@SHHNAME:=SHHNAME from ( select s.evtdate ,ifnull(s.RLDSHG,s.cshg-s.SHGBCH)/10000 as chng -- 變動股數(萬股) ,s.cshg/10000 as cshg-- 變動后持股(萬股) ,s.PCTCSHG -- 變動后持股比例% ,SHHNAME ,s.COMUNIC from pgenius.HK_SAKCHMJSHH s where SHHNAME in ( select distinct shhname from pgenius.HK_SAKCHMJSHH a where comunic=(select COMUNIC from pgenius.hk_stkcode where stkcode='00001') and ISVALID=1 and not exists(select 1 from pgenius.HK_SAKCHMJSHH where COMUNIC=a.COMUNIC and SHHNAME=a.SHHNAME and evtdate>a.evtdate) and cshg > 0) ) t1, (SELECT @rank := 0,@SHHNAME:='') t2 order by SHHNAME,evtdate desc ) t inner join pgenius.hk_stkcode o on t.COMUNIC= o.COMUNIC where t.rank<=10 order by shhname,rank