
创建分组
SELECT emp_no, COUNT(*) FROM salaries GROUP BY emp_no HAVING emp_no < 10020;
输出:
+--------+----------+
| emp_no | COUNT(*) |
+--------+----------+
| 10001 | 17 |
| 10002 | 6 |
| 10003 | 7 |
| 10004 | 16 |
| 10005 | 13 |
| 10006 | 12 |
| 10007 | 14 |
| 10008 | 3 |
| 10009 | 18 |
| 10010 | 6 |
| 10011 | 7 |
| 10012 | 10 |
| 10013 | 17 |
| 10014 | 9 |
| 10015 | 1 |
| 10016 | 5 |
| 10017 | 10 |
| 10018 | 16 |
| 10019 | 4 |
+--------+----------+
19 rows in set (0.89 sec)
这条语句的前半句表示,在工资表中查找emp_no, 以及返回该表中的所有行。但是后半句加上了GROUP_BY emp_no语句,代表着将按照emp_no进行分组。所有emp_no对应的COUNT(*)都将合并起来,最终形成这样的输出。
使用GROUP BY的一些重要规定:
GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套,可以进行更细致的操作。- 如果在
GROUP BY子句中嵌套了分组,在计算的时候会一起计算掉。 GROUP BY子句中列出的每个列都必须是检索列或有效的表达式。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。- 在进行分组计算时,除聚集计算语句外,
SELECT语句中的每个列都必须在GROUP BY子句中给出。 - 如果分组列中具有
NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。 GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
HAVING
HAVING关键词将对GROUP_BY进行过滤,类似于WHERE。
HAVING 和 WHERE的区别
WHERE在数据分组前进行过滤,而HAVING在数据分组后进行过滤。严格意义上讲,WHERE没有分组的概念,它无法和分组混用。
分组和排列
| ORDER BY | GROUP BY |
|---|---|
| 排序产生的输出 | 分组行,但输出可能不是分组的顺序 |
| 任意列都可以使用 | 只可能使用选择列或表达式列,而且必须使用每个选择表达式 |
| 不一定需要 | 如果与聚集函数一起使用,则必须使用 |
分组GROUP BY在某些情况下不一定能排序,这个时候需要结合ORDER BY可达到排序的效果。
SELECT emp_no, SUM(salary) FROM salaries GROUP BY emp_no HAVING emp_no < 10020;
分析: 从salaries表中获取emp_no,salary列,对salary列做求和计算。如果对整个列求和那明显是不合理的,所以添加了分组,按照emp_no来分组,来计算同一个emp_no所对应的salary值之和,再进行过滤到只保留emp_no小于10020的数据。
输出:
+--------+-------------+
| emp_no | SUM(salary) |
+--------+-------------+
| 10001 | 1281612 |
| 10002 | 413127 |
| 10003 | 301212 |
| 10004 | 904196 |
| 10005 | 1134585 |
| 10006 | 606179 |
| 10007 | 991574 |
| 10008 | 147923 |
| 10009 | 1409122 |
| 10010 | 460338 |
| 10011 | 348474 |
| 10012 | 469028 |
| 10013 | 891337 |
| 10014 | 476913 |
| 10015 | 40000 |
| 10016 | 374977 |
| 10017 | 870647 |
| 10018 | 1098241 |
| 10019 | 188029 |
+--------+-------------+
19 rows in set (1.07 sec)
SELECT子句顺序
| 子句 | 说明 | 是否必须使用 |
|---|---|---|
| SELECT | 要返回的列或表达式 | 是 |
| FROM | 从中检索数据的表 | 仅在从表选择数据时使用 |
| WHERE | 行级过滤 | 否 |
| GROUP BY | 分组说明 | 仅在按组计算聚集时使用 |
| HAVING | 组级过滤 | 否 |
| ORDER BY | 输出排序顺序 | 否 |
| LIMIT | 要检索的行数 | 否 |