mysql 查询 TOP N 问题

Posted 凌雨尘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql 查询 TOP N 问题相关的知识,希望对你有一定的参考价值。

Q:有一个学生成绩表,表名 stu(学生表),字段有:id(主键),name(学生姓名),subject(学科),score(分数)

1、查询该表中,所有科目都及格的学生

select name from stu group by name having MIN(score) >= 60;

说明:都及格的话,就是最低分是60以上

2、查询该表中,每门科目的前两名

select a.* from (
select *,@num := if(@subject = subject and @score>score, @num := @num + 1, IF(@score=score,@num := @num,1)) as num,@subject := subject,@score := score from stu order by subject,score desc
) as a
where num <= 2;

说明:使用存储过程处理,不过该方法风险不可控

3、查询该表中,每门科目的前 N 名

select a.* from (
select *,@num := if(@subject = subject and @score>score, @num := @num + 1, IF(@score=score,@num := @num,1)) as num,@subject := subject,@score := score from stu order by subject,score desc
) as a
where num <= N;

说明:同第二题

使用存储过程的话可能会出现一些不可避免的问题,后面的人不太好维护,不方便调试,出现错误的话也很难排查,而且报错的话很少有提示,也少有日志可以排查错误,无法适应数据库的切割,只能用于简单的业务上

《阿里巴巴java编码规范》有这样一条

其实用不用存储过程要根据业务来确定,而不能因为阿里禁止我就绝对不能使用,要把握好风险,mysql对SQL编程和复杂查询性能优化的支持实在太烂,而使用SQL Server少有这种问题,SQL Server在2008版本的时候Transact-SQL编程已经相当成熟

 

 

附:

DROP TABLE IF EXISTS `stu`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `stu` (
  `id` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  `subject` varchar(45) DEFAULT NULL,
  `score` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `stu`
--

LOCK TABLES `stu` WRITE;
/*!40000 ALTER TABLE `stu` DISABLE KEYS */;
INSERT INTO `stu` VALUES (1,\'A\',\'1\',60),(2,\'A\',\'2\',30),(3,\'B\',\'1\',60),(4,\'B\',\'2\',60),(5,\'C\',\'1\',70),(6,\'C\',\'2\',80);
/*!40000 ALTER TABLE `stu` ENABLE KEYS */;
UNLOCK TABLES;

 

以上是关于mysql 查询 TOP N 问题的主要内容,如果未能解决你的问题,请参考以下文章

MySQL获取分组后的TOP 1和TOP N记录

获取分组后的TOP 1和TOP N记录

MySQL中如何实现select top n ----Limit

MySQL用limit代替SQL Server :top

sql查询语句:top n的用法

sql mysql查询/ db片段