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

MYSQL 分组排名的更多相关文章

  1. Mysql 分组选择

    Mysql 分组选择 在其他的数据库中我们遇到分组选择的问题时,比如在分组中计算前10名的平均分 我们可以使用row_number()over() 比较方便的得到. 但是在mysql中,问题就被抛了出 ...

  2. mysql成绩排名

    关于mysql成绩排名,网上大部分只是order by简单排序,忽略了成绩相同并列名次的问题. 定义了一个表score结构为:

  3. Oracle和MySQL分组查询GROUP BY

    Oracle和MySQL分组查询GROUP BY 真题1.Oracle和MySQL中的分组(GROUP BY)有什么区别? 答案:Oracle对于GROUP BY是严格的,所有要SELECT出来的字段 ...

  4. mysql 分组和聚合函数

    mysql 分组和聚合函数 Mysql 聚集函数有5个: 1.COUNT() 记录个数(count(1),count(*)统计表中行数,count(列名)统计列中非null数) 2.MAX() 最大值 ...

  5. mysql 分组内 排序

    mysql 分组内 排序 类似于 sqlserver over partition by   因为mysql中木有sqlserver over partition by这个函数,要从sqlserver ...

  6. mysql计算排名 转

    from :http://www.cnblogs.com/aeiou/p/5719396.html http://www.cnblogs.com/zengguowang/p/5541431.html ...

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

    MySQL实现排名并查询指定用户排名功能,并列排名功能 表结构: CREATE TABLE test.testsort ( id int(11) NOT NULL AUTO_INCREMENT, ui ...

  8. mysql计算排名

    mysql计算排名,获取行号rowno 学生成绩表数据 SELECT * FROM table_score ORDER BY score DESC; 获取某个学生成绩排名并计算该学生和上一名学生成绩差 ...

  9. mysql分组取最大(最小、最新、前N条)条记录

    在数据库开发过程中,我们要为每种类型的数据取出前几条记录,或者是取最新.最小.最大等等,这个该如何实现呢,本文章向大家介绍如何实现mysql分组取最大(最小.最新.前N条)条记录.需要的可以参考一下. ...

随机推荐

  1. cocos2dx 搭建 android 平台

    Mac OS X下配置Cocos2d-x for Android(Eclipse)&IOS(Xcode)开发环境 前面一段时间只用Cocos2d-x在IOS平台下开发, 学习Cocos2d-x ...

  2. 【转】C 宏

    http://www.cs.yale.edu/homes/aspnes/pinewiki/C%282f%29Macros.html See KernighanRitchie Appendix A12. ...

  3. 转:去掉DataTable重复数据(程序示例比较)

    using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.T ...

  4. 转:DateTime的灵活运用

    //2008年4月24日 System.DateTime.Now.ToString("D"); //2008-4-24 System.DateTime.Now.ToString(& ...

  5. [转载] 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc),编写函数 strcpy(C++版)

    已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字符串,strSrc 是源字符串.不调用C++/C ...

  6. 比较字符串,equals防空指针问题

    1,比较两个字符串内容的话,用a.equals(b)比较,其中a,b是两个字符串,用a==b的话比较的是a和b的内存地址.2,如果一个字符串是变量,另一个字符串是常量的话,一定要把常量写在前面,变量写 ...

  7. Spring MVC 使用拦截器优雅地实现权限验证功能

    在上一篇 SpringAOP 实现功能权限校验功能 中虽然用AOP通过抛异常,请求转发等勉强地实现了权限验证功能,但感觉不是那么完美,应该用拦截器来实现才是最佳的,因为拦截器就是用来拦截请求的,在请求 ...

  8. 浅谈C中的malloc和free

    转自http://bbs.bccn.net/thread-82212-1-1.html非常感谢作者 浅谈C中的malloc和free 在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的 ...

  9. [AMPPZ 2013]Bytehattan

    先把题目链接贴在这里喵~ http://main.edu.pl/en/archive/amppz/2013/baj 话说真是一道让我严重怀疑我的智商的好题目, 话说此题第一感觉.嗯?似乎离线做做就可以 ...

  10. 黑马程序员——JAVA基础之抽象和接口 , 模版方法设计模式

    ------- android培训.java培训.期待与您交流! ---------- 抽象定义:           抽象就是从多个事物中将共性的,本质的内容抽取出来.           例如:狼 ...