Mysql中exists子查询语句的使用,取出每组中最高的前n名的信息
2016-09-21 14:07
477 查看
一、准备测试的表和数据
二、插入一些测试数据
基本工作准备完毕,回到正题,在实际开发环境中,有时需要查询每个分组例如销量最高的前几名等等。可以使用如下SQL语句(此处是Mysql):
取出每组中value值最高的前三条记录:
select a.* from cat a where exists (select count(*) from cat where cat_id = a.cat_id and value > a.value having Count(*) < 3) order by a.cat_id,a.value desc;
exists的子查询中,有引用外层查询,现在来分析:
首先,按照sql执行顺序,先看from部分,毫无疑问,查询了所有的表记录,等同于select * from cat,记录如下:
进一步了解执行的过程:
现在,我拿到外层查询的第一行,也就是上图的第一行。此时子查询中取出当前表cat中cat_id=1并且values值大于2的,毫无疑问,有2条记录,满足条件小于3(用到了having语句,对中间结果进行过滤等等处理),此时exists满足条件,返回true。外层查询第一条记录被保存。到最后cat_id为1,value为1的,count(*)为3,子查询返回的是false。所以上图中的第3条记录不会被保存。
然后一番选取之后,外层查询得到了满足条件的结果集。最后通过order by将结果集排序,然后显示如下:
create table cat( id int not null auto_increment primary key, cat_id int, value int, name varchar(30) );
二、插入一些测试数据
insert into cat (cat_id,name,value) values ('1','name1', '2'); insert into cat (cat_id,name,value) values ('1','name2', '21'); insert into cat (cat_id,name,value) values ('1','name3', '1'); insert into cat (cat_id,name,value) values ('1','name4', '3'); insert into cat (cat_id,name,value) values ('2','name5', '54'); insert into cat (cat_id,name,value) values ('2','name6', '4'); insert into cat (cat_id,name,value) values ('2','name7', '24'); insert into cat (cat_id,name,value) values ('2','name8', '23'); insert into cat (cat_id,name,value) values ('3','name9', '57'); insert into cat (cat_id,name,value) values ('3','name10','45'); insert into cat (cat_id,name,value) values ('3','name11','12'); insert into cat (cat_id,name,value) values ('3','name12','23');
基本工作准备完毕,回到正题,在实际开发环境中,有时需要查询每个分组例如销量最高的前几名等等。可以使用如下SQL语句(此处是Mysql):
取出每组中value值最高的前三条记录:
select a.* from cat a where exists (select count(*) from cat where cat_id = a.cat_id and value > a.value having Count(*) < 3) order by a.cat_id,a.value desc;
exists的子查询中,有引用外层查询,现在来分析:
首先,按照sql执行顺序,先看from部分,毫无疑问,查询了所有的表记录,等同于select * from cat,记录如下:
mysql> select * from cat; +----+--------+--------+-------+ | id | cat_id | name | value | +----+--------+--------+-------+ | 1 | 1 | name1 | 2 | | 2 | 1 | name2 | 21 | | 3 | 1 | name3 | 1 | | 4 | 1 | name4 | 3 | | 5 | 2 | name5 | 54 | | 6 | 2 | name6 | 4 | | 7 | 2 | name7 | 24 | | 8 | 2 | name8 | 23 | | 9 | 3 | name9 | 57 | | 10 | 3 | name10 | 45 | | 11 | 3 | name11 | 12 | | 12 | 3 | name12 | 23 | +----+--------+--------+-------+ 12 rows in set (0.00 sec)然后,exits子查询的特点是返回true或者是false,并不会返回结果集,这点很重要!等同于外层查询通过where了一个exists的子查询返回的是true还是false来判断外层查询的这条记录是否保存到结果集中。
进一步了解执行的过程:
现在,我拿到外层查询的第一行,也就是上图的第一行。此时子查询中取出当前表cat中cat_id=1并且values值大于2的,毫无疑问,有2条记录,满足条件小于3(用到了having语句,对中间结果进行过滤等等处理),此时exists满足条件,返回true。外层查询第一条记录被保存。到最后cat_id为1,value为1的,count(*)为3,子查询返回的是false。所以上图中的第3条记录不会被保存。
然后一番选取之后,外层查询得到了满足条件的结果集。最后通过order by将结果集排序,然后显示如下:
+----+--------+--------+-------+ | id | cat_id | name | value | +----+--------+--------+-------+ | 2 | 1 | name2 | 21 | | 4 | 1 | name4 | 3 | | 1 | 1 | name1 | 2 | | 5 | 2 | name5 | 54 | | 7 | 2 | name7 | 24 | | 8 | 2 | name8 | 23 | | 9 | 3 | name9 | 57 | | 10 | 3 | name10 | 45 | | 12 | 3 | name12 | 23 | +----+--------+--------+-------+ 9 rows in set (0.00 sec)
相关文章推荐
- MYSQL5下查询语句CASE WHEN 子查询的使用
- 使用过的MySql查询语句[待续...]
- 使用SQL语句查询Mysql日志存放位置
- thinkphp 使用原生mysql语句 联合查询
- mysql 查询表的行数和空间使用及其它信息
- MYSQL:使用慢查询日志定位效率较低的SQL语句
- 【MySQL】如何使用C#+MySQL实现一条MySQL语句进行多表查询
- Mysql中DATE_SUB 使用方法结合查询一天内,一周内,一月内的信息实例讲解
- mysql查询语句select-limit使用详解
- 合理使用MySQL索引建立高质量查询语句
- 基于mysql查询语句的使用详解
- 使用MySQL的慢查询日志找到低效的SQL语句
- 用sql语句取出mysql 数据库中表的字段的说明信息
- LAMP开发精要(13):PHP中使用mysql_stmt(预处理语句)处理select查询结果
- 使用SQL语句查询数据库信息及表结构
- 使用索引统计信息(Index Statistics)优化查询语句,提高查询效率
- Mysql中使用UNION语句进行多表连接查询
- mySql查询语句Limit使用
- 【MySQL】如何使用C#+MySQL实现一条MySQL语句进行多表查询