读书笔记

《SQL基础教程》阅读笔记4

2018-11-18  本文已影响9人  Athenaearl

子句书写顺序:
SELECT->FROM ->WHERE-> GROUP BY ->HAVING ->ORDER BY

聚合与排序

对表进行聚合查询

聚合函数

用于汇总的函数称为聚合函数,所谓聚合就是将多行汇总为一行
5个常用的聚合函数

示例(COUNT):

mysql> SELECT COUNT(*) FROM Product;
+----------+
| COUNT(*) |
+----------+
|        8 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT COUNT(purchase_price) FROM Product;
+-----------------------+
| COUNT(purchase_price) |
+-----------------------+
|                     6 |
+-----------------------+
1 row in set (0.00 sec)

mysql> SELECT COUNT(*), COUNT(purchase_price) FROM Product;
+----------+-----------------------+
| COUNT(*) | COUNT(purchase_price) |
+----------+-----------------------+
|        8 |                     6 |
+----------+-----------------------+
1 row in set (0.00 sec)

说明:
COUNT(*) 代表的是计算所有的行数,就算有一行所有的值都是NULL,还是会被计算在内
COUNT(列名) 代表的是这一列中所有不是NULL的行数

示例(SUM):
说明:SUM 会忽略掉所有的NULL,而不会将NULL加上去(所有NULL参与的运算的结果都是NULL),这里可以认为将NULL看作0来计算

mysql> SELECT SUM(purchase_price), SUM(sale_price) FROM Product;
+---------------------+-----------------+
| SUM(purchase_price) | SUM(sale_price) |
+---------------------+-----------------+
|               12210 |           16780 |
+---------------------+-----------------+
1 row in set (0.00 sec)

示例(AVG)
可以将NULL看作是0来计算,但是本质上不是这么做的
AVG做的就是将SUM的值/值的个数

mysql> SELECT AVG(purchase_price), AVG(sale_price) FROM Product;
+---------------------+-----------------+
| AVG(purchase_price) | AVG(sale_price) |
+---------------------+-----------------+
|           2035.0000 |       2097.5000 |
+---------------------+-----------------+
1 row in set (0.00 sec)

示例(MAX 和 MIN)

mysql> SELECT MAX(regist_date), MIN(regist_date) FROM Product;
+------------------+------------------+
| MAX(regist_date) | MIN(regist_date) |
+------------------+------------------+
| 2009-11-11       | 2008-04-28       |
+------------------+------------------+
1 row in set (0.01 sec)

使用聚合函数删除重复值(关键字 DISTINCT)

回顾一下:使用count函数
如果count(单列列名) 返回的是该列非NULL的行数
如果count(*) 返回的是所有的行数
如果想要获得没有重复值的行数,则需要DISTINCT关键字

mysql> SELECT COUNT(DISTINCT product_type) FROM Product;
+------------------------------+
| COUNT(DISTINCT product_type) |
+------------------------------+
|                            3 |
+------------------------------+
1 row in set (0.00 sec)

对表进行分组

mysql> SELECT product_type, COUNT(*) FROM Product GROUP BY product_type;
+--------------+----------+
| product_type | COUNT(*) |
+--------------+----------+
| 办公用品     |        2 |
| 厨房用具     |        4 |
| 衣服         |        2 |
+--------------+----------+
3 rows in set (0.00 sec)

说明:
这里的意思是,打印 product_type 和 count 的值,这些值来自于根据product_type 分的组中,也就是说这里面分了三组,分别是 办公用具、厨房用具、衣服 ,count则是分别计算每一组出现的次数
而且,如果有NULL的话,NULL会被单独算一组

加入where子句
mysql> SELECT product_type, COUNT(*) FROM Product WHERE regist_date = '2009-09-20' GROUP BY product_type;
+--------------+----------+
| product_type | COUNT(*) |
+--------------+----------+
| 厨房用具     |        2 |
| 衣服         |        1 |
+--------------+----------+
2 rows in set (0.00 sec)

说明:先找到时间是2009-09-20的行,然后按照product_type 分的类,办公用品这一类没有这个时间注册的,因此没有这一项,计数时候,厨房用品这一天的有2件因此count的值为2

常见错误:

  1. SELECT col1, col2 FROM product GROUP BY col1;
    这种形式是允许的,因为,比如col1 代表时间,col2 代表产品种类,可能一个时间有多个产品被登记,那么就会导致混乱,因此这种形式是不被允许的
  2. GROUP BY 语句中使用别名:
    SELECT col1 AS name1 FROM product GROUP BY name1;
    这是由于内部的执行顺序导致的,在进行到分组时候,它还不知道别名是什么。但是这个分数据库管理系统,比如笔者用的Mysql就不会导致错误。但是这不是标准的sql语句
  3. 认为GROUP BY输出的结果是排好序的:
    实际上其输出结果是随机的,如果想要排序,需要进行指定
  4. 在WHERE 子句中使用聚合函数:
SELECT product_type, COUNT(*)
FROM product
WHERE COUNT(*) = 2
GROUP BY product_type;

这种写法是错误的。实际上想要达到效果,应该使用having 子句
只有SELECT 、HAVING、ORDER BY子句可以使用聚合函数

此外:
可以注意到:

SELECT DISTINCT product_type FROM product;

SELECT product_type FROM product GROUP BY product_type;

得到的效果是一样的

为聚合结果指定条件

WHERE 能够指定的是行条件,而HAVING 则是可以指定组条件,因此HAVING 子句可以使用聚合函数

mysql> SELECT product_type, COUNT(*) FROM Product GROUP BY product_type HAVING COUNt(*)=2;
+--------------+----------+
| product_type | COUNT(*) |
+--------------+----------+
| 办公用品     |        2 |
| 衣服         |        2 |
+--------------+----------+
2 rows in set (0.00 sec)

说明:
表中根据product_type 分类,但是只选择那些count值为2 的组

WHERE是先将满足条件的行挑出来,然后再分组

而HAVING 是先分组然后再将合适的组挑出来,因此HAVING只能是组的条件,行条件是不可以的。但是,由于分组是根据一个列来分组,那么HAVING 可以使用这个列的条件
即:

SELECT col1 FROM table GROUP BY col1 HAVING col1 = col1_element1;

但是想要这种情况的话 WHERE 也可以做到,甚至来说,更加推荐用WHERE

对查询结果进行排序

ORDER BY 子句

mysql> SELECT product_type, product_name FROM Product ORDER BY sale_price;
+--------------+--------------+
| product_type | product_name |
+--------------+--------------+
| 办公用品     | 圆珠笔       |
| 办公用品     | 打孔机       |
| 厨房用具     | 叉子         |
| 厨房用具     | 擦菜板       |
| 衣服         | T恤衫        |
| 厨房用具     | 菜刀         |
| 衣服         | 运动T恤      |
| 厨房用具     | 高压锅       |
+--------------+--------------+
8 rows in set (0.00 sec)

mysql> SELECT product_type, product_name FROM Product ORDER BY sale_price DESC;
+--------------+--------------+
| product_type | product_name |
+--------------+--------------+
| 厨房用具     | 高压锅       |
| 衣服         | 运动T恤      |
| 厨房用具     | 菜刀         |
| 衣服         | T恤衫        |
| 厨房用具     | 擦菜板       |
| 办公用品     | 打孔机       |
| 厨房用具     | 叉子         |
| 办公用品     | 圆珠笔       |
+--------------+--------------+
8 rows in set (0.00 sec)

mysql> SELECT product_type, product_name FROM Product ORDER BY sale_price DESC, product_id;
+--------------+--------------+
| product_type | product_name |
+--------------+--------------+
| 厨房用具     | 高压锅       |
| 衣服         | 运动T恤      |
| 厨房用具     | 菜刀         |
| 衣服         | T恤衫        |
| 厨房用具     | 擦菜板       |
| 办公用品     | 打孔机       |
| 厨房用具     | 叉子         |
| 办公用品     | 圆珠笔       |
+--------------+--------------+
8 rows in set (0.00 sec)

说明:

  1. 排序键可以使用别名
  2. 可以使用聚合函数
  3. 可以用数字来代指SELECT 子句中第几个元素
    SELECT col1, col2 ,col3 FROM table ORDER BY 2 DESC , 1;
    代表 按 col2 的降序排,按col1 的升序排。但是不推荐使用,不易于使用
上一篇 下一篇

猜你喜欢

热点阅读