注意:MAX/MIN 函数和 SUM/AVG 函数有一点不同,那就是 SUM/ AVG 函数只能对数值类型的列使用,而 MAX/MIN 函数原则上可以适用于任何数据类型的列。
(2)注意 NULL聚合函数普遍会将 NULL 排除在外( COUNT 函数例外),具体如下:
1、COUNT 函数的结果根据参数的不同而不同。COUNT(*)会得到包含 NULL 的数据行数,而 COUINT(<列名>) 会得到不包含 NULL的数据行数。
SELECT COUNT(DISTINCT <列名>) 可以得到不包含 NULL 且 不重复的数据行数。
2、SUM 函数将 NULL 忽略,也可理解成视为 0。
3、AVG 函数将 NULL 忽略,即不参与分母也不参与分子。
2、对表进行分组 —— GROUP BYGROUP BY 一般习惯跟聚合函数搭配使用。
(1)进阶 - GROUP BY 与 数学中的 类它们全都是非空集合。
所有子集的并集等于划分之前的集合。
任何两个子集之间都没有交集。
在数学(群论)中,满足以上3 个性质的各子集称为“类”(partition),将原来的集合分割成若干个类的操作称为“分类”。
所以 GROUP BY 和 下面要介绍的 PARTITION BY 都是用来划分 类 的函数。
问:去重用 GROUP BY 还是 DISTINCT ?如果用了 GROUP BY 却没用聚合函数,多半是为了去重,但有 DISTINCT 呀:
-- 1、DISTINCT SELECT DISTINCT "product_type" FROM "Product" -- 2、GROUP BY SELECT "product_type" FROM "Product" GROUP BY "product_type"注意:上面两种结果,都会保留 NULL 行。
答:用 DISTINCT。可读性优先。
常见错误 1 一一 在 SELECT 子句中书写了多余的列原因:多余的列并没有被聚合,当然无法显示。
解决方案:SELECT 子句中只能存在以下三种元素:
常数
聚合函数
GROUP BY 子句中指定的列名(也就是聚合键)
常见错误 2 一一 在 GROUP BY 子句中写了在 SELECT 里指定的列的别名原因:跟执行顺序有关:FROM→ WHERE→ GROUP BY→ SELECT
解决方案:其实 PostgreSQL 支持这种写法。但推荐为了遵循 标准 SQL ,尽量不要这样写。
常见错误 3 一一 在 WHERE 子句中使用聚合函数例子:
-- 错误1: SELECT "product_type", COUNT(*) FROM "Product" WHERE COUNT(*) = 2 GROUP BY "product_type" -- 错误2: SELECT "product_type", COUNT(*) FROM "Product" GROUP BY "product_type" WHERE COUNT(*) = 2 -- 正确: SELECT "product_type", COUNT(*) FROM "Product" GROUP BY "product_type" HAVING COUNT(*) = 2原因:WHERE 子句不可以使用聚合函数,因为他针对的是行而不是组。
解决方案:请用下面会介绍的 HAVING 子句代替这里的 WHERE。
3、为聚合结果指定条件 —— HAVING (1)WHERE vs. HAVINGWHERE 子句 —— 指定行条件
HAVING 子句 —— 指定组条件
例子:
-- WHERE 子句 SELECT * FROM "Product" WHERE "product_type" = '体育' -- HAVING 子句 SELECT "product_type", COUNT(*) FROM "Product" GROUP BY "product_type" HAVING COUNT(*) = 2 -- WHERE + HAVING 子句 SELECT "product_type", COUNT(*) FROM "Product" GROUP BY "product_type" WHERE "product_price" > 10 HAVING COUNT(*) = 2 (2)HAVING 也可不加 GROUP BYHAVING 不加 GROUP BY(也可认为是对空字段进行了 GROUP BY 操作),整张表会被视为一个组。
SELECT '存在缺失的编号' AS gap FROM "Product" HAVING COUNT(*) <> MAX("product_id");这种情况下,就不能在SELECT 子句里引用原来的表里的列了,要么就得像示例里一样使用常量,要么就得像 SELECT COUNT(*) 这样使用聚合函数。
类似于使用窗口函数时不指定 PARTITION BY 子句,就是把整个表当作一个窗口来处理。
(3)对聚合键的筛选是放 WHERE 还是 HAVING ?例子:
-- 1、放在 HAVING SELECT "product_type", COUNT (*) FROM "Product" GROUP BY "product_type" HAVING "product_type" <> '衣服' -- 2、放在 WHERE SELECT "product_type", COUNT (*) FROM "Product" WHERE "product_type" <> '衣服' GROUP BY "product_type"结论:放在 WHERE 子句。(能写在 WHERE 子句里的条件就不要写在 HAVING 子句里)
理由:
1、通过 WHERE 子句指定条件时,由于排序之前就对数据进行了过滤,因此能够减少排序的数据量。但 HAVING 子句是在排序之后オ对数据进行分组的,因此与在 WHERE 子句中指定条件比起来,需要排序的数据量就会多得多。
2、可以对 WIHERE 子句指定条件所对应的列创建索引,这样也可以大幅提高处理速度。
GROUP BY 生成的是派生表,HAVING 无法使用索引。
4、对查询结果进行排序 —— ORDER BY (1)用法SELECT 语句末尾添加 ORDER BY 子句来明确指定排列顺序。
select * FROM "Activity" ORDER BY "id" DESCASC —— ascendent(上升的)【省略即默认】
DESC —— descendent(下降的)
执行顺序:FROM→ WHERE→ GROUP BY→ HAVING→ SELECT→ ORDER BY
注意:ORDER BY 子句中也可以使用聚合函数,跟 SELECT 里一样。
(2)注意 NULL排序键中包含 NULL 时,会在开头或末尾进行汇总。究竟是在开头显示还是在末尾显示,并没有特殊规定。每家 DBMS 可能不一样。