MySQL:数据分组

380 阅读3分钟

前言

数据分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。

在我们的实际使用中,数据分组更多和聚集函数一起使用从而提供更强大的数据汇总统计功能。

这篇的内容是自己学习上的一些总结记录。

内容

数据分组大体上包括两部分的内容。一部分是根据分组规则将数据分组成一个个的逻辑组,称为分组数据。另一部分是对分出来的逻辑组进行特定条件的过滤筛选,称为过滤分组。

前者需要使用上GROUP BY子句,后者需要使用上HAVING子句。

分组数据

GROUP BY子句用于数据分为多个逻辑组,以便能对每一组进行聚集计算。

GROUP BY子句在使用形式上,如下:

    SELECT [column_name] FROM [table_name] GROUP BY [column_name_1], [colum_name_2], [...];

上面形式中,如果我们在[column_name]中使用聚集函数,函数会在每一个和分组上进行聚集计算,得到每一个分组的聚集值。这种分组和聚集函数结合使用的方式,解决了数据在分类统计上的许多场景。

GROUP BY子句的使用,还有如下特点:

  • GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套,为数据分组提供更细致的控制;

  • 如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总;

  • GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名;

  • 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出;

  • 如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL,它们将分为一组;

  • GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。

过滤分组

过滤操作,用于根据特定的过滤条件过滤出我们所需要的数据。上面提及到的WHERE子句就是一种过滤功能的子句,但是,它却并不适用于GROUP BY构建出来的逻辑分组上。

对这种逻辑上的分组进行过滤,我们需要使用HAVING子句。

    SELECT [column_name]
    FROM [table_name]
    GROUP BY [column_name]
    HAVING [filter_condition];

HAVING子句在使用格式上和WHERE子句基本一致,支持所有WHERE的操作符,句法使用相同,除了关键字不同。另外,两者有这些差异特点需要特别注意:

  • WHERE在数据分组前进行过滤,过滤的目标是行,而HAVING在数据分组后进行过滤,过滤的目标是分组;

  • HAVING的过滤条件表达式中支持聚集函数,WHERE则不支持;

WHERE子句和HAVING子句两者在同一条语句中是可以同时出现的。同时应用于一条语句上,WHERE的过滤会被先执行。

针对一条包含WHERE子句和HAVING子句的SELECT语句,举个例子:

  1. 首先根据WHERE子句的过滤条件检索出所有符合条件的行,得到第一个结果集;

  2. 对第一个结果集执行分组操作,得到第二个逻辑分组的结果集;

  3. 对第二个逻辑分组的结果集,根据HAVING子句的过滤条件过滤出所有符合条件的分组,得到第三个结果集;

  4. 对第三个结果集执行SELELCT的计算表达式、列检索等等操作,最后进行结果集限制(如果有的话);

根据上面的例子,我们就能有个两者执行优先级上的大概认识。

参考资料