一、创建分组
mysql> SELECT vend_id, COUNT(*) AS num_prods
-> FROM products
-> GROUP BY vend_id;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
+---------+-----------+
GROUP BY子句指示MySQL分组数据,然后对每个分组而不是整个结果集进行聚集, 引擎会自动完成这种工作。
在具体使用 GROUP BY 子句前,需要知道一些重要的规定。
GROUP BY 子句可以包含任意数目的列。这使得能对分组进行嵌套,为数据分组提供更细致的控制。
group by a,b,c -- 先按a分组,如果a相同,再按b分组,如果b相同,再按c分组,最终统计的是最小分组的信息如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总。如果使用了聚集函数,那么聚合函数针对操作的是最小的分组后的信息, 根据最小分组来分别统计信息
GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。因为GROUP BY优先于SELECT执行。
除聚集计算语句外,SELECT 语句中的每个列都必须在GROUP BY子句中列出。
使用group by 分组之后, select 语句只能指定聚合函数或者包含在group by中指定的字段(SELECT只能出现分组后的整体信息,不能出现组内的详细信息),否则返回的行数不一致
构建查询时,Projection 子句的投影列表中的所有非聚集列还必须包含在 GROUP BY 子句中。具有 GROUP BY 子句的 SELECT 语句必须针对每一组返回一行。列示在 GROUP BY 后面的列能够在一组中只反映一个特异值,并且可以返回该值。但是,未列示在 GROUP BY 后面的列可在包含在组中的行中包含不同的值。 二、过滤分组 HAVING
除了能用GROUP BY分组数据外,MySQL还允许过滤分组,规定包括哪些分组,排除哪些分组。基于【完整的分组】而不是【个别的行】进行过滤。
提到过滤,肯定想到WHERE子句。不过WHERE过滤指定的是"行"而不是"分组"。事实上,WHERE没有分组的概念。
为此MySQL提供了另外一个子句,HAVING。HAVING 非常类似于WHERE 。唯一的差别是WHERE 过滤“行”,而HAVING 过滤“分组”。所有关于WHERE 的技术和选项都适用于HAVING,它们的句法是相同的,只是关键字不同而已。HAVING支持所有WHERE操作符。 HAVING 和 WHERE 区别:
WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。WHERE是过滤行,而HAVING必须基于完整的分组过滤。(其他用法都相同) 三、SELECT 子句顺序
SELECT
FROM
WHERE -- 行级过滤
GROUP BY
HAVING -- 组级过滤
ORDER BY
LIMIT SQL执行的逻辑顺序:
(1) FROM left_table
(3) join_type JOIN right_table (2) ON join_condition
(4) WHERE where_condition
(5) GROUP BY group_by_list
(6) WITH {cube | rollup}
(7) HAVING having_condition
(8) SELECT (9) DISTINCT (11) top_specification select_list
(9) ORDER BY order_by_list
(10) LIMIT 逻辑查询处理阶段简介