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
时间: 2024-10-12 12:01:56

MYSQL 分组排名的相关文章

MySql 分组排序取时间最大的一条记录

SELECT A.* FROM digital_asset A, (SELECT name, max(last_updated) max_day FROM digital_asset GROUP BY name) B WHERE A.name = B.name AND A.last_updated = B.max_day SELECT A . * FROM bbs_threads A, ( SELECT digest, max( dateline ) max_dateline FROM bbs_

mysql计算排名

mysql计算排名,获取行号rowno 学生成绩表数据 SELECT * FROM table_score ORDER BY score DESC; 获取某个学生成绩排名并计算该学生和上一名学生成绩差,是并列排名 SELECT *, (SELECT count(DISTINCT score) FROM table_score AS b WHERE a.score<b.score)+1 AS rank, #获取排名,并列 (SELECT b.score FROM table_score AS b

Oracle和MySQL分组查询GROUP BY

Oracle和MySQL分组查询GROUP BY 真题1.Oracle和MySQL中的分组(GROUP BY)有什么区别? 答案:Oracle对于GROUP BY是严格的,所有要SELECT出来的字段必须在GROUP BY后边出现,否则会报错:“ORA-00979: not a GROUP BY expression”.而MySQL则不同,如果SELECT出来的字段在GROUP BY后面没有出现,那么会随机取出一个值,而这样查询出来的数据不准确,语义也不明确.所以,作者建议在写SQL语句的时候,

mysql查询排名

student_work表 student_info表 sql语句:按grade从高到低排名 结果: mysql查询排名

MySQL实现排名并查询指定用户排名功能,并列排名功能

MySQL实现排名并查询指定用户排名功能,并列排名功能 表结构: CREATE TABLE test.testsort ( id int(11) NOT NULL AUTO_INCREMENT, uid int(11) DEFAULT 0 COMMENT '用户id', score decimal(10, 2) DEFAULT 0.00 COMMENT '分数', PRIMARY KEY (id) ) ENGINE = INNODB AUTO_INCREMENT = 1 CHARACTER SE

MySQL分组与连表查询

MySQL分组与连表查询 2019-08-23 1.MySQL分组 按照某一个属性降数据进行分组,通过关键字:group by:通常分组会与聚合函数联合使用. 聚合函数常用的有:min,max,sum,avg,count. 比如统计男女生人数 --性别表 create table gendertable( id int auto_increment primary key, gender char(10) )engine=innodb default charset=utf8; insert i

Mysql 分组查询出现&#39;this is incompatible with sql_mode=only_full_group_by&#39;的解决办法

由于Mysql自动开启了 only_full_group_by,所以若查询的字段不在group by里面,则分组报错. 解决办法其一:mysql配置,关闭only_full_group_by,这种办法自行百度 下面说第二种办法: 除去group_by 以外的参数加上any_value(*) 如:SELECT type_id,any_value(`name`)  FROM ts_product GROUP BY type_id; Mysql 分组查询出现'this is incompatible

mysql分组查询时,讲多个值合并在一行显示

mysql根据字段进行分组查询时,相同字段的数据,只会显示一个,如果要想让这个字段的所有数据,显示在一行里,可以在查询时用GROUP_CONTAT函数,默认数据合并以逗号,分开

[MySQL] 分组排序取前N条记录以及生成自动数字序列,类似group by后 limit

前言:         同事的业务场景是,按照cid.author分组,再按照id倒叙,取出前2条记录出来.        oracle里面可以通过row_number() OVER (PARTITION BY cid,author ORDER BY id DESC) 表示根据cid,author分组,在分组内部根据id排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的),而mysql数据库就没有这样的统计函数,需要自己写复杂的sql来实现. 1,录入测试数据 USE csd