zoukankan      html  css  js  c++  java
  • MYSQL 分组排名

    今天遇到一个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
  • 相关阅读:
    更改开机运行级别
    三个路由的路由表信息
    网络
    网卡配置文件与网络命令显示不一致
    使CentOS7恢复网卡传统命名
    删除CentOS7的虚拟网卡
    将克隆的eth3和eth4改为eth0和eth1
    单臂路由--1个物理网卡绑定多个IP地址
    洛谷P1098 字符串的展开
    洛谷P1086 花生采摘
  • 原文地址:https://www.cnblogs.com/champaign/p/4021815.html
Copyright © 2011-2022 走看看