创建分组

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 要检索的行数