|
Andy Niu Help
1.0.0.0
|
变量 | |
| 汇总数据 | |
| 分组数据 | |
| 使用子查询 | |
详细描述
变量说明
| 使用子查询 |
1、所谓子查询,就是嵌套在其他查询中查询,经常使用的场景,如下:
mysql> select name,teaid from stu where teaid in (1,2);
+----------+-------+
| name | teaid |
+----------+-------+
| Andy | 1 |
| Bill | 2 |
| Caroline | 1 |
| David | 2 |
| Eric | 1 |
| Andy | 2 |
| David | 1 |
| Eric | 2 |
+----------+-------+
8 rows in set
mysql> select name,teaid from stu where teaid in (select id from tea where name='Mr Li' or name ='Mr Zhang');
+----------+-------+
| name | teaid |
+----------+-------+
| Andy | 1 |
| Bill | 2 |
| Caroline | 1 |
| David | 2 |
| Eric | 1 |
| Andy | 2 |
| David | 1 |
| Eric | 2 |
+----------+-------+
8 rows in set
2、作为计算字段使用子查询,统计每个老师的学生个数,如下:
mysql> select name,(select count(1) from stu where stu.teaid = tea.id) as StuNum from tea;
+----------+--------+
| name | StuNum |
+----------+--------+
| Mr Li | 4 |
| Mr Zhang | 4 |
| Mrs Niu | 0 |
+----------+--------+
3 rows in set
执行过程如下:
投影name,对于tea表的每一个id取值,传给子查询,统计学生个数,也就是说,子查询执行3次。
相对于第一种子查询,这种子查询叫做相关子查询,因为这种子查询涉及到外部查询。
3、对于group by,也可以使用相关子查询来实现,如下:
mysql> select name,avg(age) from stu group by name;
+----------+----------+
| name | avg(age) |
+----------+----------+
| Andy | 15.0000 |
| Bill | 17.0000 |
| Caroline | 17.0000 |
| David | 11.5000 |
| Eric | 19.0000 |
+----------+----------+
5 rows in set
mysql> select distinct name,(select avg(age) from stu as A where A.name = stu.name) as AvgAge from stu;
+----------+---------+
| name | AvgAge |
+----------+---------+
| Andy | 15.0000 |
| Bill | 17.0000 |
| Caroline | 17.0000 |
| David | 11.5000 |
| Eric | 19.0000 |
+----------+---------+
5 rows in set
执行过程:对于每一个distinct name,传给相关子查询,用于统计平均值。
| 分组数据 |
1、汇总数据是对满足条件的所有记录进行聚集。考虑下面的需求,将记录根据某个字段(某些字段)分成多个逻辑组,
再对每个逻辑组进行聚集计算,怎么办?
2、使用group by 进行分组,如下:
select name,avg(age) from stu group by name;
3、考虑下面两个语句的区别:
select name from stu where id>2;
select name,avg(age) from stu where id>2 group by name;
前一个语句,先选择,再投影,select字段name
后一个语句,先选择,然后进行逻辑分组,得到多个逻辑分组,每个分组里面,一个name关联一组id和一组age。
对每个分组进行投影,select字段name,对其它字段进行聚集计算。
特别注意:对于分组,select的内容(也就是投影的内容)一般包括分组的字段,和其它字段的汇总。
当然,也可以select不是分组的字段,语法没错。但是,这样做并没有意义。
因为进行逻辑分组之后,对于其他字段,一个分组中往往包含多个数据,进行select,只会获取其中的第一个数据,
这个数据往往没有意义,对其它字段的一组数据进行聚集计算才有意义。
4、如果过滤分组,比如检查age的平均值,怎么办?
使用 having,这个时候的过滤条件往往是 其它字段的聚集函数,如下:
select name,max(age) from stu group by name having max(age)>17;
5、select的字句顺序和执行顺序
select xxx from xxx where xxx group by xxx having xxx order by xxx limit xxx;
执行顺序:
a、首先根据where进行行级选择
b、group by 进行分组
c、通过having 进行分组过滤
d、然后order by xxx limit
e、最后投影
思考:为什么投影是最后进行的操作?
因为行过滤,分组过滤,有可能是根据其它的字段进行过滤,如果先投影就没法再进行过滤了。
| 汇总数据 |
1、有时候我们需要汇总数据,而不是查询记录。Mysql提供5个聚集函数。
count
max
min
avg
sum
2、示例如下:
mysql> select count(age) from stu;
+------------+
| count(age) |
+------------+
| 5 |
+------------+
1 row in set
mysql> select max(age) from stu;
+----------+
| max(age) |
+----------+
| 19 |
+----------+
1 row in set
3、考虑下面的需求,某一个字段,对于不同的值进行聚集,怎么办?
使用distinct,如下:
select sum(distinct age) from stu;
注意:函数max和min,可以对不同的值进行聚集,但这样做并没有意义。因为去除相同的值,并不影响最大值和最小值。
4、如果同时求出平均值和最大值,怎么办?
使用组合聚集函数,也就是对多个聚集函数组合,如下:
mysql> select count(age),avg(age),max(age) from stu;
+------------+----------+----------+
| count(age) | avg(age) | max(age) |
+------------+----------+----------+
| 5 | 15.8000 | 19 |
+------------+----------+----------+
1 row in set
mysql> select count(age),avg(distinct age),max(age) from stu;
+------------+-------------------+----------+
| count(age) | avg(distinct age) | max(age) |
+------------+-------------------+----------+
| 5 | 15.5000 | 19 |
+------------+-------------------+----------+
1 row in set
Copyright (c) 2015~2016, Andy Niu @All rights reserved. By Andy Niu Edit.