前言
本章将介绍如何分组数据,以便能汇总表内容的子集。这涉及两个新SELECT语句子句,分别是GROUP BY子句和HAVING子句。
一、数据分组
分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算
二、创建分组
分组是在SELECT语句的GROUP BY子句中建立的。
用法:
SELECT 列名, 计算字段 FROM 表名 GROUP BY 排序分组依赖列名;
示例:
mysql> SELECT age, COUNT(*) AS num_prods FROM userinfo GROUP BY age; # GROUP BY子句指示MySQL按age排序并分组数据
+------+-----------+
| age | num_prods |
+------+-----------+
| 18 | 2 |
| 22 | 1 |
| 24 | 1 |
| 13 | 1 |
| NULL | 1 |
+------+-----------+
5 rows in set (0.00 sec)
重要规定:
- GROUP BY子句可以包含任意数目的列。
- 如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。
- GROUP BY子句中列出的每个列都必须是检索列或有效的表达式。
- 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出。
- 如果分组列中具有NULL值,则NULL将作为一个分组返回。
- GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
使用WITH ROLLUP关键字,可以得到每个分组以及每个分组汇总级别(针对每个分组)的值
示例:
mysql> SELECT age, COUNT(*) AS num_prods FROM userinfo GROUP BY age WITH ROLLUP;
+------+-----------+
| age | num_prods |
+------+-----------+
| NULL | 1 |
| 13 | 1 |
| 18 | 2 |
| 22 | 1 |
| 24 | 1 |
| NULL | 6 |
+------+-----------+
6 rows in set (0.00 sec)
三、过滤分组
所有类型的WHERE子句都可以用HAVING来替代。唯一的差别是WHERE过滤行,而HAVING过滤分组。
用法:
SELECT 列名, 计算字段 FROM 表名 GROUP BY 排序分组依赖列名 HAVING 分组条件;
示例:
# 过滤分组中user_info = 2的组
mysql> SELECT age,COUNT(*) AS user_info FROM userinfo GROUP BY age HAVING user_info = 2;
+------+-----------+
| age | user_info |
+------+-----------+
| 18 | 2 |
+------+-----------+
1 row in set (0.00 sec)
- HAVING和WHERE的差别 :WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。
示例:
mysql> SELECT age,COUNT(*) AS user_info FROM userinfo WHERE status = 0 GROUP BY age HAVING user_info = 1;
+------+-----------+
| age | user_info |
+------+-----------+
| 18 | 1 |
| 22 | 1 |
| 24 | 1 |
| 13 | 1 |
+------+-----------+
4 rows in set (0.00 sec)
四、分组和排序
虽然GROUP BY和ORDER BY经常完成相同的工作,但它们是非常不同的。
ORDER BY 与 GROUP BY
| ORDER BY | GROUP BY | |
|---|---|---|
| 作用 | 排序产生输出 | 分组行。但输出可能不是分组的排序 |
| 限制 | 任意列都可以使用 | 只可能使用选择列或表达式列,而且必须使用每个选择列表达式 |
| 使用 | 不一定需要 | 如果与聚集函数一起使用列(或表达式),则必须使用 |
- 不要忘记ORDER BY:一般在使用GROUP BY子句时,应该也给出ORDER BY子句。这是保证数据正确排序的唯一方法。千万不要仅依赖GROUP BY排序数据。
# 按照age进行排序
mysql> SELECT age,COUNT(*) AS user_info FROM userinfo WHERE status = 0 GROUP BY age HAVING user_info = 1 ORDER BY age;
+------+-----------+
| age | user_info |
+------+-----------+
| 13 | 1 |
| 18 | 1 |
| 22 | 1 |
| 24 | 1 |
+------+-----------+
4 rows in set (0.01 sec)
五、SELECT子句排序
SELECT子句及其顺序
| 子句 | 说明 | 是否必须使用 |
|---|---|---|
| SELECT | 要返回的列或表达式 | 是 |
| FROM | 从中检索数据的表 | 仅在从表选择数据时使用 |
| WHERE | 行级过滤 | 否 |
| GROUP BY | 分组说明 | 仅在按组计算聚集时使用 |
| HAVING | 组级过滤 | 否 |
| ORDER BY | 输出排序顺序 | 否 |
| LIMIT | 要检索的行数 | 否 |
小结
在第12章中,我们学习了如何用SQL聚集函数对数据进行汇总计算。本章讲授了如何使用GROUP BY子句对数据组进行这些汇总计算,返回每个组的结果。我们看到了如何使用HAVING子句过滤特定的组,还知道了ORDER BY和GROUP BY之间以及WHERE和HAVING之间的差异。
174万+

被折叠的 条评论
为什么被折叠?



