背景:有一个系统,每个用户在注册的时候,用户会提交自己的民族。
需求:运营部门需要统计出来系统中各民族的人数,以便设计线下活动和销售计划。
方案一:专门设计一张表,包括“民族”和“人数”两个字段,用于存储每个民族的人数,每当用户注册时,便更新这张表的数据,使对应的民族人数加1。
方案二:每次需要统计时,我们将所有用户按照不同民族分成若干组,然后统计每组的人数。
即便抛开计算机编程、回到最原始的现实,假如你作为班主任招生一个班级,校长让你统计最终班上各民族的人数。你一定也不会在招生之初就找个小本本从每个民族的0人开始计数,来一个学生就在对应的民族的数字上加1(或者划“正”字)。
你一定是在招生的时候先不管这些,等招满之后,把全班学生按照民族分成几个小组,然后用笔记下每个小组代表的民族和其中的人数。
所以上面的例子中,采用哪种方案显而易见。
如果把结果按照统计的最小单位划分,查询语句分两种:
统计结果的每一条数据都是真实存在于数据库的某张表的,只是可能只展示了其中几个字段而已。
统计结果的每一条数据并不真实存在于数据库的某张表,但它们却可以分别代表着一类数据,这就是分组查询,将真实存在的数据分成若干组,并展示每一组的概要信息(比如这一组的个数,或汇总数,相当于Excel中的求和、计数等)。
上一节我们介绍了简单的查询,还有下一节我们要介绍的关联查询,都属于第一种,它们查询的最小单位都是一条真实存在的数据。这一节我给大家介绍第二种查询(分组查询)的写法。
若要对数据分组,需要做到以下步骤
先使用from指定从哪些表中提取数据
用where条件圈定要参与分组的数据范围,不写代表在from指定的表中,没有其他范围限制。
使用group by描述分组的依据字段(可以是多个,用逗号隔开,多个代表按多个条件为依据分组,只有这几个条件完全一致的数据,才能分到一组里面)
用select字段描述要展示哪些字段
关于上面第4点,由于已经把数据分组了,所以结果展示的每一条数据就变成了一类或一群数据,所以能展示的字段必须能代表着一群数据,如果按照民族分组之后,就无法在最终结果上展示姓名这一字段,因为每一组里面可能会用很多姓名不同的数据,没法找出一个能代表其对应的那一组数据,但按照民族分组后,最终结果上是可以展示民族的,因为每一组里面所有的人的民族都是一样的。除此之外,select部分还可以包含聚合函数。总结起来一句话,分组查询中,select部分只能写group by后面的字段和聚合函数。
聚合函数就类似于excel中的求和、计数等函数,sql中的计数就是count(*),求和就是sum(...)。如果在group by函数中加了聚合函数,它们会以每一组为范围,分别计算出相应的聚合结果。
比如下面这个分组查询,意思是把学生表中年龄超过20岁的,按照民族分组,并展示“民族”、“每一组数量”两个字段:
selectETHINC, count(*)
fromt_student
whereage > 20
group byETHINC
这里值得强调的是:这里的where会先被数据库执行,然后在交给后面的sql命令。使用where来圈定一个范围来做分组。如果我们想在分好组之后,筛选掉一些不符合条件的分组,可以使用having。这里的having从一定角度上看的话,其功能都类似于普通查询的where关键字。
比如,仍然使用上面的例子的话,公司需要统计出,那个民族的人数超过20人
selectETHINC, count(*)
fromt_student
whereage > 20
group byETHINC
havingcount(*) > 20
每个民族的人数只有分组之后才知道,而where是用来圈定参与分组的数据范围的,它会在分组之前被数据库解析,所以这种需求只能使用having语句来实现。
本节关于group by的介绍先到这里,师父领进门,修行在个人:)
下一篇介绍关联查询。
领取专属 10元无门槛券
私享最新 技术干货