MYSQL 分组排名

转:https://www.cnblogs.com/champaign/p/4021815.html

今天遇到一个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

最后附上本人修改的代码

SELECT
	*, (
		SELECT
			rank
		FROM
			(
				SELECT
					s1id,
					rname,
					@rank := (
						CASE
						WHEN @Grp = rid THEN
							@rank + 1
						ELSE
							1
						END
					) AS rank,
					@Grp := rid AS grp2
				FROM
					(
						SELECT
							*
						FROM
							v_wx_mini_shop_user_info
					) tmp,
					(SELECT @rank := 0 ,@grp := 0) a
				ORDER BY
					rid DESC
			) RESULT
		WHERE
			s1id = ssa.s1id
	) AS crank,
	(
		SELECT
			rank
		FROM
			(
				SELECT
					s1id,
					cname,
					cid,
					@rank := (
						CASE
						WHEN @Grp = cid THEN
							@rank + 1
						ELSE
							1
						END
					) AS rank,
					@Grp := cid AS grp2
				FROM
					(
						SELECT
							*
						FROM
							v_wx_mini_shop_user_info
					) tmp,
					(SELECT @rank := 0 ,@grp := 0) a
				ORDER BY
					cid DESC
			) RESULT
		WHERE
			s1id = ssa.s1id
	) AS cirank
FROM
	(
		SELECT
			a.*,
			@n :=@n + 1 rank
		FROM
			(
				SELECT
					r.id rid,
					r. NAME rname,
					p.id pid,
					p. NAME pname,
					c.id cid,
					c. NAME cname,
					s1.id s1id,
					s1.shopName s1Name,
					su.id suid,
					su. NAME suname,
					COUNT(s2.user_id) reAmount,
					s1.shopType,
					s1.custgroup
				FROM
					wx_mini_shop_info s1
				LEFT JOIN wx_mini_user_info s2 ON s1.id = s2.manager_shop_id
				LEFT JOIN wx_mini_promoter_profile pp ON pp.shop_id = s1.id
				LEFT JOIN wx_mini_region p ON pp.province_id = p.id
				LEFT JOIN wx_mini_region c ON pp.city_id = c.id
				LEFT JOIN wx_mini_region r ON pp.region_id = r.id
				LEFT JOIN (
					SELECT
						id,
						NAME
					FROM
						wx_mini_region
					WHERE
						type = 2
				) su ON pp.subregion_id = su.id
				WHERE
					s1.shopType IN ("GT", "KA")
				GROUP BY
					s1.id
				ORDER BY
					reAmount DESC
			) a,
			(SELECT @n := 0) d
	) ssa

猜你喜欢

转载自blog.csdn.net/qq_39313596/article/details/90202661