3-1 对表进行聚合查询
聚合函数:用于汇总的函数
聚合:将多行汇总为一行
COUNT:计算表中的记录数(行数)
通常,聚合函数会对NULL以外的对象进行汇总,所有的聚合函数,如果以列名为参数,那么在计算之前就已经把 NULL 排除在外了。
但是只有COUNT函数例外,COUNT函数的结果根据参数的不同而不同,COUNT(*)会得到包含NULL在内的全部数据的行数,而COUNT(<列名>)会得到NULL之外的数据行数。
MAX/MIN 函数和 SUM/AVG 函数有一点不同,MAX/MIN函数几乎适用于所有数据类型的列,SUM/AVG函数只适用于数值类型的列。
使用聚合函数删除重复值(关键字DISTINCT)
SELECT COUNT(DISTINCT product_type)
FROM Product;
SELECT SUM(sale_price), SUM(DISTINCT sale_price)
FROM Product;
注:DISTINCT 必须写在括号中。这是因为必须要在计算行数之前删除 product_type 列中的重复数据
3-2 对表进行分组
GROUP BY 子句中指定的列称为聚合键或者分组列
当聚合键中包含 NULL 时,也会将 NULL 作为一组特定的数据,在结果中会以“不确定”行(空行)的形式表现出来
与聚合函数和GROUP BY子句有关的常见错误:
1、在SELECT子句中书写了多余的列(聚合键之外的列名)(因为并不一定一对一)
使用聚合函数时,SELECT 子句中只能存在以下三种元素。 ● 常数 ● 聚合函数 ● GROUP BY子句中指定的列名(也就是聚合键)
2、在WHERE子句中使用聚合函数
只有SELECT子句和HAVING子句(以及ORDER BY子句)中能够使用聚合函数。
3-3 为聚合结果指定条件
WHERE子句用来指定数据行的条件,HAVING子句用来指定分组的条件。
HAVING 子句中能够使用的 3 种要素: ● 常数 ● 聚合函数 ● 聚合键
在思考 HAVING 子句的使用方法时,把一次汇总后的结果(类似表 3-2 的表)作为 HAVING 子句起始点的话更容易理解
聚合键所对应的条件不应该书写在HAVING子句当中,而应该书写在WHERE子句当中。
1、根本原因是 WHERE 子句和 HAVING 子句的作用不同。如前所述,HAVING 子句是用来指定“组”的条件的。因此,“行”所对应的条件还是应该写在 WHERE 子句当中。
WHERE 子句 = 指定行所对应的条件
HAVING 子句 = 指定组所对应的条件
2、将条件写在 WHERE 子句中要比写在 HAVING 子句中的处理速度更快,返回结果所需的时间更短。
(从 DBMS 的内部运行机制来考虑)
使用 COUNT 函数等对表中的数据进行聚合操作时,DBMS 内部就会进行排序处理。排序处理是 会大大增加机器负担的高负荷的处理。因此,只有尽可能减少排序的行数,才能提高处理速度。 WHERE 子句指定条件:排序之前就对数据进行了过滤,能够减少排序的数据量。但
HAVING 子句:在排序之后才对数据进行分组,需要排序的数据量就会多得多。
此外,WHERE 子句可以对 WHERE 子句指定条件所对应的列创建索引,大幅提高处理速度。创建索引是一种非常普遍 的提高 DBMS 性能的方法。
3-4 对查询结果进行排序
ORDER BY 子句写在 SELECT 语句的末尾,因为对数据行进行排序的操作必须在结果即将返回时执行。
排序键:ORDER BY 子句中书写的列名称
▲执行顺序 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
NULL的顺序
使用含有 NULL 的列作为排序键时, NULL 会在结果的开头或末尾汇总显示,因为不能对 NULL 使用比较运算符,即不能对 NULL 和数字进行排序,也不能与字符串和日期比较大小
注:
1、在ORDER BY子句中可以使用SELECT子句中定义的别名。
2、在ORDER BY子句中可以使用SELECT子句中未使用的列和聚合函数。
3、在ORDER BY子句中不要使用列编号。