SQL

SQL 知识量:22 - 44 - 129

10.1 数据分组><

创建分组- 10.1.1 -

通过使用where子句可以对符合某一条件的行进行汇总计算,例如:查询来自美国的游客人数等。但是如果要同时查询计算每种条件下的数据时该怎么办呢?例如:查询来自各个国家的游客人数。使用where子句一项项的查询汇总实在太麻烦,而且还需要先知道有哪些国家。这时,可以使用数据分组技术来解决难题。

分组是使用select语句的group by子句建立的。

例如:查询来自各个国家的游客人数(人次)。

select country,count(*) from visitor group by country;

结果:

+---------+----------+
| country | count(*) |
+---------+----------+
| NULL    |        2 |
| China   |        1 |
| Japan   |        1 |
| UK      |        2 |
| USA     |        2 |
+---------+----------+

因为有些游客没有登记国家名称,所以他们作为一类(NULL)进行了统计。

使用group by子句前,需要知道一些重要的规定:

  • group by子句可以包含任意数目的列,因此可以对分组进行嵌套,从而更细致的进行分组。

  • 如果进行了分组嵌套,数据将在最后指定的分组上进行汇总。

  • group by子句中列出的所有列必须是检索列或有效的表达式,但不能是聚集函数。如果使用表达式进行分组,则select中的表达式与group by子句中的表达式必须完全相同,不能使用别名。

  • 大多数DBMS不允许group by列带有长度可变的数据类型(例如:文本数据等)。

  • 除了聚集计算语句外,在group by子句中给出select语句的每个检索列是一个好习惯。

  • 如果分组中包含具有NULL的值,则NULL将作为一个分组返回。多行NULL值将分为一组。(以上例子即是如此。)

  • group by子句必须出现在where子句之后,order by子句之前。

  • 有些DBMS允许根据列在select语句中的位置来指定group by中的列。例如:group by 2表示按照select检索的第2个列来分组。这很方便,但是容易出错,不推荐使用。

过滤分组- 10.1.2 -

除了使用group by子句进行分组外,还可以对分组进行过滤,去掉不需要的分组。

在分组上进行过滤需要使用having子句,having子句与where子句十分相似,having支持所有where操作符(通配符等),where的所有技术和选项也都适用于having,但是它们之间唯一的区别是,where对行进行过滤,而having对分组进行过滤。

例如:查询来自各个国家的游客人数(人次),并且游客人数不能少于2人。

select country,count(*) from visitor group by country having count(*)>=2;

结果:

+---------+----------+
| country | count(*) |
+---------+----------+
| NULL    |        2 |
| UK      |        2 |
| USA     |        2 |
+---------+----------+

理解where子句与having子句的区别,最重要的一点是:where在分组前进行过滤,having在分组后进行过滤。

例如:修改一下上面的列子,查询来自各个国家的游客人数(人次),并且游客人数不能少于2人,没有登记国家名称的除外。

select country,count(*) 
from visitor 
where country is not null 
group by country having count(*)>=2;

结果:

+---------+----------+
| country | count(*) |
+---------+----------+
| UK      |        2 |
| USA     |        2 |
+---------+----------+

这样,国家名称为NULL的行在分组前就被排除了。