sql分组后查找每组的前几条记录语句

常用的sqlserver,mysql,oracle等数据库sql语句都是遵循sql标准,但是每种数据库都有自己的特点。

如果想做到程序兼容性更好,后期维护更方便,还是建议尽量使用各种数据库通用的sql语句(当然你也可以使用数据库独有特性)。

这里举个看似简单,缺难道不少人的例子:

分组查询每个班级分数前2名学生的记录

1.准备数据:

DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `NAME` varchar(10) default NULL,
  `class` varchar(20) default NULL,
  `score` varchar(20) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `test` VALUES ('1', '进一', '09-01', '299');
INSERT INTO `test` VALUES ('2', '虹二', '09-01', '259');
INSERT INTO `test` VALUES ('3', '张三', '09-01', '289');
INSERT INTO `test` VALUES ('4', '李四', '09-01', '277');
INSERT INTO `test` VALUES ('5', '张楚', '09-02', '287');
INSERT INTO `test` VALUES ('6', '小米', '09-02', '277');
INSERT INTO `test` VALUES ('7', '婷婷', '09-02', '257');
INSERT INTO `test` VALUES ('8', '月月', '09-02', '265');

2.查询分析
按class分组,然后取id靠前的两名,相信大多数人都能想到基本组合:
SELECT a.* FROM test a ORDER BY a.class, a.score;
注:sqlserver中可以用top n的写法,mysql中用limit 0 ,n,那么oracle中又得变了。
并且top0,n和Limit 0,n只能取到最前的n位,但如何能取到每个班的前n位呢,就无从下手了。
下面具体分析一下这题的解法:
获取每个class的前2位:
SELECT * FROM test a WHERE (SELECT COUNT(*) FROM test t WHERE t.class = a.class AND t.score > a.score) < 2;
遍历所有记录a,a.class
每条记录进行如下对比:
同班t,t.class=a.class  且分数比他高(score大于他)的记录的条数<2
(比他分数高的人的数量小于2; 比他分数高的人有1个,他是第2名; 比他分数高的人有0个,他是第1名; 所以筛选出来的是前2名)
然后用该条记录与同班t中的所有记录比较,只有当班上t不超过两个人(含两个人)比该记录score高的话,该记录才被认定为该记录score排名前2,然后显示出来。






你可能感兴趣的:(sql)