MySQL必知必会--分 组 数 据

时间:2021-09-18 01:54:21

数据分组

目前为止的所有计算都是在表的所有数据或匹配特定的 WHERE 子句的
数据上进行的。提示一下,下面的例子返回供应商 1003 提供的产品数目

MySQL必知必会--分 组 数 据

但如果要返回每个供应商提供的产品数目怎么办?或者返回只提供
单项产品的供应商所提供的产品,或返回提供10个以上产品的供应商怎
么办?
这就是分组显身手的时候了。分组允许把数据分为多个逻辑组,以
便能对每个组进行聚集计算

创建分组

分组是在 SELECT 语句的 GROUP BY 子句中建立的。理解分组的最好办
法是看一个例子

MySQL必知必会--分 组 数 据
上面的 SELECT 语句指定了两个列, vend_id 包含产品供应商的ID,
num_prods 为计算字段(用 COUNT(*) 函数建立)。 GROUP BY 子句指
示MySQL按 vend_id 排序并分组数据。这导致对每个 vend_id 而不是整个表
计算 num_prods 一次。从输出中可以看到,供应商 1001 有 3 个产品,供应商
1002 有 2 个产品,供应商 1003 有 7 个产品,而供应商 1005 有 2 个产品

因为使用了 GROUP BY ,就不必指定要计算和估值的每个组了。系统
会自动完成。 GROUP BY 子句指示MySQL分组数据,然后对每个组而不是
整个结果集进行聚集

在具体使用 GROUP BY 子句前,需要知道一些重要的规定。

  • GROUP BY 子句可以包含任意数目的列。这使得能对分组进行嵌套,
    为数据分组提供更细致的控制。
  • 如果在 GROUP BY 子句中嵌套了分组,数据将在最后规定的分组上
    进行汇总。换句话说,在建立分组时,指定的所有列都一起计算
    (所以不能从个别的列取回数据)。
  • GROUP BY 子句中列出的每个列都必须是检索列或有效的表达式
    (但不能是聚集函数)。如果在 SELECT 中使用表达式,则必须在
    GROUP BY 子句中指定相同的表达式。不能使用别名。
  • 除聚集计算语句外, SELECT 语句中的每个列都必须在 GROUP BY 子
    句中给出。
  • 如果分组列中具有 NULL 值,则 NULL 将作为一个分组返回。如果列
    中有多行 NULL 值,它们将分为一组。
  • GROUP BY 子句必须出现在 WHERE 子句之后, ORDER BY 子句之前。

使用 ROLLUP 使用 WITH ROLLUP 关键字,可以得到每个分组以
及每个分组汇总级别(针对每个分组)的值,如下所示

MySQL必知必会--分 组 数 据

过滤分组

除了能用 GROUP BY 分组数据外,MySQL还允许过滤分组,规定包括
哪些分组,排除哪些分组。例如,可能想要列出至少有两个订单的所有
顾客。为得出这种数据,必须基于完整的分组而不是个别的行进行过滤

HAVING 非常类似于 WHERE 。事实上,目前为止所
学过的所有类型的 WHERE 子句都可以用 HAVING 来替代。唯一的差别是
WHERE 过滤行,而 HAVING 过滤分组

HAVING 支持所有 WHERE 操作符 在第6章和第7章中,我们学习
了 WHERE 子句的条件(包括通配符条件和带多个操作符的子
句)。所学过的有关 WHERE 的所有这些技术和选项都适用于
HAVING 。它们的句法是相同的,只是关键字有差别

MySQL必知必会--分 组 数 据

这条 SELECT 语句的前3行类似于上面的语句。最后一行增加了
HAVING 子句,它过滤 COUNT(*) >=2 (两个以上的订单)的那些
分组。
正如所见,这里 WHERE 子句不起作用,因为过滤是基于分组聚集值而
不是特定行值的

HAVING 和 WHERE 的差别 这里有另一种理解方法, WHERE 在数据
分组前进行过滤, HAVING 在数据分组后进行过滤。这是一个重
要的区别, WHERE 排除的行不包括在分组中。这可能会改变计
算值,从而影响 HAVING 子句中基于这些值过滤掉的分组

那么,有没有在一条语句中同时使用 WHERE 和 HAVING 子句的需要呢?
事实上,确实有。假如想进一步过滤上面的语句,使它返回过去12个月
内具有两个以上订单的顾客。为达到这一点,可增加一条 WHERE 子句,过
滤出过去12个月内下过的订单。然后再增加 HAVING 子句过滤出具有两个
以上订单的分组
为更好地理解,请看下面的例子,它列出具有 2 个(含)以上、价格
为 10 (含)以上的产品的供应商

MySQL必知必会--分 组 数 据

分组和排序

虽然 GROUP BY 和 ORDER BY 经常完成相同的工作,但它们是非常不同
的。表13-1汇总了它们之间的差别

MySQL必知必会--分 组 数 据

表13-1中列出的第一项差别极为重要。我们经常发现用 GROUP BY 分
组的数据确实是以分组顺序输出的。但情况并不总是这样,它并不是SQL
规范所要求的。此外,用户也可能会要求以不同于分组的顺序排序。仅
因为你以某种方式分组数据(获得特定的分组聚集值),并不表示你需要
以相同的方式排序输出。应该提供明确的 ORDER BY 子句,即使其效果等
同于 GROUP BY 子句也是如此

不要忘记 ORDER BY 一般在使用 GROUP BY 子句时,应该也给
出 ORDER BY 子句。这是保证数据正确排序的唯一方法。千万
不要仅依赖 GROUP BY 排序数据

检索总计订单价格大于等于 50 的订
单的订单号和总计订单价格

MySQL必知必会--分 组 数 据

SELECT子句顺序

下面回顾一下 SELECT 语句中子句的顺序。表13-2以在 SELECT 语句中
使用时必须遵循的次序,列出迄今为止所学过的子句

MySQL必知必会--分 组 数 据

MySQL必知必会--分 组 数 据

我们学习了如何用SQL聚集函数对数据进行汇总计算。
本章讲授了如何使用 GROUP BY 子句对数据组进行这些汇总计算,返回每
个组的结果。我们看到了如何使用 HAVING 子句过滤特定的组,还知道了
ORDER BY 和 GROUP BY 之间以及 WHERE 和 HAVING 之间的差异。