因为该列没有包含在聚合函数或 group by 子句中。_SQL基础:第3章 聚合与排序

回到目录

聚合函数

聚合函数是用于汇总的函数,即将多行汇总为一行。有如下5个常用的聚合函数:

  • COUNT:计算表的行数
  • SUM:计算表中数值列中数据的和
  • AVG:计算表中数值列中数据的平均值
  • MAX:求表中任意列的最大值
  • MIN:求表中任意列的最小值

COUNT的用法:

-- 例如

若将包含null的列作为count的参数,则count(列名)得到的结果是不包含null的行数。但count(*)例外,它不会排除null。

以列名为参数时,sum(列名)也一样,计算的时候会把null排除在外。

同理,avg(列名),求的该列平均值,是分子分母都排除了null后计算出来的结果。

max和min,求最大最小值,几乎适用于所有数据类型。而sum和avg只适用于数值类型。

同时使用DISTINCT和聚合函数删除重复值

-- 例如

对表进行分组的GROUP BY子句

SELECT 

若表中有三种类别的物品,分别是衣服、厨房用具、办公用品,总共8行记录,其中衣服2行,厨房用具4行,办公用品2行,则上述语句得到结果为:

30873104455a668a8b05b18428f361ef.png

GROUP BY后面的参数称为聚合键,是表分组的依据。

使用GROUP BY时,null也会被视为一组,会在结果中以空白的形式出现。

书写顺序与执行顺序

截至目前学习的语句中,有如下书写顺序:

select -> from -> where -> group by

书写顺序不能乱。

同样重要的是执行顺序:

from -> where -> group by -> select

书写顺序和数据库内部的执行顺序并不相同。

同时使用WHERE和GROUP BY

-- 例如

根据上面提到的执行顺序可知,会先执行where语句对表格中的记录进行“过滤”,然后再对剩下的记录执行group by。

使用聚合函数和GROUP BY时的注意事项

  • 使用了聚合函数的select后面的参数只能有三种情况:
    • 聚合键
    • 聚合函数
    • 常数

因此使用聚合函数时,以上三种以外的情况不能出现在select后面。

  • group by后不能书写列的别名。

因为别名是在select子句中定义的,而根据执行顺序,select在group by之后执行,因此执行到group by时,select中的别名此时数据库系统还不知道。

  • group by语句结果的显示顺序是随机的。
  • 不能在where子句中使用聚合函数

只有select、having和order by子句中能够使用聚合函数。

DISTINCT和GROUP BY

有时候,distinct和group by都可以实现删除重复数据的功能。考虑如下语句:

-- distinct

上述两段代码得到的结果是一样的,而且都会把null作为一个独立的结果返回(对distinct来说,null也是一种类别),执行速度也差不多。那么该如何选择呢?

答案很简单,如果只是单纯地想删除重复数据,使用distinct足矣;而想对表进行分组并计算汇总结果时,则使用group by。如果不打算分组并计算汇总结果,却使用了group by来单纯地删除重复数据,则在逻辑上容易引起他人的误解。

能为聚合结果指定条件的HAVING子句

说到指定条件,很容易想到where,但where只能指定记录(行)的条件,不能用来指定分组后组的条件。而having则是可以对组指定条件的子句。语法如下:

SELECT 

显然,如果不使用having,行数不是2的组及其行数也会被提取出来。

书写顺序与执行顺序

增加了having子句后书写顺序为:

select -> from -> where -> group by -> having

执行顺序为:

from -> where -> group by -> having -> select

HAVING子句的构成要素

与包含group by的select子句一样,having后面的参数也只能是以下三种情况:

  1. 聚合键
  2. 聚合函数
  3. 常数

WHERE与HAVING

有时候,where与having都可以实现在group by分组后指定条件。但是上文提到过where子句中不能使用聚合函数,那可以使用什么来指定条件呢?

答案是聚合键。group by后的where虽不能使用聚合函数指定条件,但可以使用聚合键。这样一来,可以完成和having一样的功能。考虑如下语句:

-- where

可以发现如果要对分组后的组指定条件,且该条件与聚合键相关,则where和having均能满足需求。但是更推荐将聚合键相关的条件写在where中,理由有两个:

  1. 理解容易。where的功能:指定行(记录)的条件;having的功能:指定组的条件。聚合键对应的条件应该属于行的条件,聚合函数对应的条件则属于组的条件。
  2. 执行速度更快。这种情况下,where比having处理速度更快。因为使用分组后select子句中使用聚合函数往往会增加机器的负担,聚合操作的负担往往比较大,而如果使用了where,则在分组、聚合前就已经对表的行数进行了过滤(因为where执行顺序优于group by),行数少了,处理的负担自然就小了。如果使用的是having,则分组、聚合时的数据量会比使用where更多。

使用ORDER BY进行排序

select语句查询的结果中,记录的顺序是随机的,如果需要排序,则需要在末尾添加order by子句。

SELECT 

若想指定降序排列,则需要在排序键后添加DESC关键字,升序则添加ASC关键字。还可以省略关键字,省略后则默认按升序排列。

还可以在order by后指定多个排序键。这样一来,会优先使用左侧的键排序,若还无法排出先后,再使用右侧的键。这时,ASC和DESC关键字则写在各自的排序键的后面。

现在来考虑一下关于null的排序,第2章提到过,不能对null使用比较运算符,既null不能被比较大小,自然也就无法被排序。因此,使用含有null的列作为排序键时,null会在结果的开头或末尾汇总显示(开头或是末尾取决于DBMS)。

排序键还可以使用不包含在select中的列,不仅如此,order by还可以使用聚合函数,就像之前提到的,select、having、order by中可以使用聚合函数。

-- 例如

书写顺序与执行顺序

增加了order by子句后书写顺序为:

select -> from -> where -> group by -> having -> order by

执行顺序为:

from -> where -> group by -> having -> select -> distinct -> order by

由执行顺序可知,select执行后才轮到order by,因此order by子句中是可以使用select中定义的别名的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值