数据库基础(2):count、sum、group by、having、order by、limit的综合应用

一、count():返回、计算结果集的行数;

1、count()和sum()函数的区别:

一个(count)是统计结果集的总行数;    一个(sum)是计算所有(符合条件)数值的总和;

mysql> select * from chengji;
+------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 张三 | 数学    |    90 |
| 张三 | 语文    |    50 |
| 张三 | 地理    |    40 |
| 李四 | 语文    |    55 |
| 李四 | 政治    |    45 |
| 王五 | 政治    |    30 |
+------+---------+-------+
6 rows in set (0.00 sec)


用count(列)的时候,即:select  count(score)from chengji; 这句查询的意思是:先做 select  score from chengji; 的查询,然后统计出返回的结果集的总行数;


sum(列)的时候,计算的是 符合条例 数值的总和;

2、count(*)和count(1)、count(columnName)的区别:

(1)从统计的结果上:

count(*)和count(1)会统计出结果集表中所有的记录数, 包含字段为NULL的记录;

count(columnName):在统计的时候,如果字段值为NULL,则不会计入总数(不统计字段为NULL的记录);

(1)从统计的效率上:

如果只有一个字段,则count(*)的效率是最优的;

如果有主键,则count(主键)的效率是最优的;

其他情况下,一般count(1)的效率是最优的;

二、groud by、having的总和应用

1、根据下表。查询出2门及2门以上不及格者的平均成绩;
mysql> select * from chengji;
+------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 张三 | 数学    |    90 |
| 张三 | 语文    |    50 |
| 张三 | 地理    |    40 |
| 李四 | 语文    |    55 |
| 李四 | 政治    |    45 |
| 王五 | 政治    |    30 |
+------+---------+-------+
6 rows in set (0.00 sec)

## 一种错误做法

mysql> select name,count(score < 60) as k,avg(score) from chengji group by name having k>=2;

错误分析:首先,此语句先执行:select name from chengji (where 1) : 得出:查询出所有人的名字;

mysql> select name from chengji;
+------+
| name |
+------+
| 张三 |
| 张三 |
| 张三 |
| 李四 |
| 李四 |
| 王五 |
+------+
6 rows in set (0.00 sec)

mysql>

然后:再次执行:select count(score<60) as k,avg(score) from chengji group by name;  按照姓名,进行分组,统计出每组的行数(即每个人的科目数),计算出每个组的平级分数;得出:


此时的K是,按照分组,统计出的每个人的科目数,而不是挂科数:故:最后在用having>2筛选,显然错误;

## 另一种错误做法:

mysql> select name,avg(score) from chengji where score<60 group by name having count(*)>=2;

错误分析:首先,此语句先执行:select name from chengji where score <60;  先把score <60 的人给查询出来;得出:


然后,再执行:select name,avg(score) from chengji where score<60 group by name;按照名字进行分组,求出每组人的平级分,此时,显然错误,第一次score<60只查询出的是挂科的人以及对应的分数,而再次分组求平均分,则只求的是 每个人 挂科的平均分 而不是 整体的 平级分;

## 正确方法1:

先求出每个人的平级分,然后再筛选出挂科数>=2的;

每个人平级分:


每个人的挂科数:


注意:此时用的是sum()求和函数,比较运算符 返回的数值为0或者1(假或者真);  不是用count,count则返回的是按照分组每个人分数的总行数,每个人下的分数都统计,包含挂科以及不挂科的:

最终得出:


## 正确方法2:

先查询出2门以及两门以上不及格者:


即;为张三、李四,需要在筛选出来;


然后,算出,这个表中name人物的平均分;


或者直接简写一个表的查询,直接得出name张三、李四的值;


综上:从where到group by、再到having的流程为:先查询,在分组(计算),最后筛选;

三、order by 应用;

order by 字段名 asc(升序), order by 字段名 desc(降序);默认是asc。在不写的情况下;

多条件综合排序的时候,用 (逗号) 进行分割;


四、limit 应用;

limit [offset=0] N;  其中offset表示的偏移量,跳过几个(行),N表示取出的数量,行数;


前三名到前五名,即:跳过了(偏移了)2个,所以offset = 2,一共需要取出3个,即: limit 2,3;

五、练习应用以及聚合函数注意点;


上述的查询语句,是取出的最大商品价格以及其对于的商品名称;

如果用max(shop_price)聚合函数来只能取出最大商品价格,不能与最大商品价格的名字相互匹配;

因为,max(shop_price)相当于一个一个新的字段列,一个原表格的投影,是最大的商品单独一个字段一行,

但是如果select后面加个goods_name字段,则会一下取出所有的商品名字(goods_name),那么多goods_name商品名称,哪一个与之相匹配呢?



猜你喜欢

转载自blog.csdn.net/prdslf001001/article/details/79959401