《SQL必知必会》--分组数据

第十课 分组数据

前面两课,我们已经学习了数据分析函数,在此时,我们回想一下所学内容,是不是我们所学的函数,基本都处于SELECT语句后面呢。也就是我常说的主语句之中。那么在条件语句中,有没有什么数据处理方式呢?今天介绍两种。

目前为止,我们所有的计算都是在表的所有数据或者匹配特定的WHERE子句的数据基础上进行的。

如果要返回每个供应商提供的产品数目,该怎么办?或者返回只提供一个产品的所有供应商名单,怎么办?

这时候就需要分组大显身手了。使用分组可以将数据分为多个逻辑组,对每个数据组进行聚集计算。

创建分组

在学习之前,我以为分组子句GROUP()有多么复杂,还需要自己去思考如何对表进行逻辑分析和分组等等。

结果等我看例子时,我才发现我错的离谱,,,

首先看下面:

1
2
3
4
5
select vend_id,
count(*) as num_vend,
vend_address
from vendors
group by vend_id;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
******************** 1. row *********************
vend_id: BRE02
num_vend: 1
vend_address: 500 Park Street
******************** 2. row *********************
vend_id: BRS01
num_vend: 1
vend_address: 123 Main Street
******************** 3. row *********************
vend_id: DLL01
num_vend: 1
vend_address: 555 High Street
******************** 4. row *********************
vend_id: FNG01
num_vend: 1
vend_address: 42 Galaxy Road
******************** 5. row *********************
vend_id: FRB01
num_vend: 1
vend_address: 1000 5th Avenue
******************** 6. row *********************
vend_id: JTS01
num_vend: 1
vend_address: 1 Rue Amusement
6 rows in set

上面的输出结果是按照记录形式单条记录的输出,在MySQL中使用快捷键CTRL+ALT+ENTER

下面是表格形式输出:

1
2
3
4
5
6
7
8
vend_id  num_vend   vend_address
------------------------------------
BRE02 1 500 Park Street
BRS01 1 123 Main Street
DLL01 1 555 High Street
FNG01 1 42 Galaxy Road
FRB01 1 1000 5th Avenue
JTS01 1 1 Rue Amusement

使用$group \quad by$子句前,需要知道一些重要规定。

  • GROUP BY 子句可以包含任意数目的列,因而可以对分组进行嵌套,更细致地进行分组。
  • 如果嵌套分组,数据将在最后制定的分组上进行汇总。
  • GROUP BY 子句中列出的每列必须是检索列或有效的表达式(聚集函数除外)。
  • 除去聚集函数外,SELECT的每一列必须在GROUP BY中列出。

虽然分组子句可以拼接,但是,一般情况下,也就是只对单列进行分组并计算出现的次数。再高阶一点,就是对A列进行分组,并呈现B列聚集函数。
突然感觉没那么香了,甚至有一些鸡肋?好吧,不算鸡肋,只是作用比我想象的要小很多了。

过滤分组

HAVING子句过滤分组

在进行分组后,可能还需要过滤一些分组,使其不出现。

提到过滤数据,可能想到WHERE子句,但是在这里却不管用。

因为:WHERE子句过滤行,而HAVING子句过滤分组

事实上

目前为止所学的WHERE子句指令方式都可以用到HAVING子句中。

WHERE 和 HAVING的具体区别:

这里有另外一种理解方法,WHERE在数据分组前进行过滤,而HAVING在数据分组后进行过滤。

1
2
3
4
5
select cust_country, cust_address,count(*)
from customers
where cust_country = 'USA'
group by cust_country, cust_address
having count(cust_address) = 1;

这段代码的含义是先过滤出来美国客户,然后对客户国籍和客户地址进行分类,最后过滤出只出现一次的地址。

SELECT子句顺序

目前为止,我们已经学习了多条指令,那么这些指令在SQL语言中是否应该有排序,以便规范编写及运行代码呢?

SELECT子句及其顺序

子句 说明 是否必须使用
SELECT 要返回的列或表达式
FROM 从中检索数据的表 仅在从表选择数据时使用
WHERE 行级过滤
GROUP 分组说明 仅在按组计算聚集时使用
HAVING 组级过滤
ORDER 输出排序顺序

小结

越写越慢了,慢慢的出现需要思考一会才能理解的指令了。