SQL必知必会
陈旸
清华大学计算机博士
立即订阅
10179 人已学习
课程目录
已完结 49 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词丨SQL可能是你掌握的最有用的技能
免费
第一章:SQL语法基础篇 (19讲)
01丨了解SQL:一门半衰期很长的语言
02丨DBMS的前世今生
03丨学会用数据库的方式思考SQL是如何执行的
04丨使用DDL创建数据库&数据表时需要注意什么?
05丨检索数据:你还在SELECT * 么?
06丨数据过滤:SQL数据过滤都有哪些方法?
07丨什么是SQL函数?为什么使用SQL函数可能会带来问题?
08丨什么是SQL的聚集函数,如何利用它们汇总表的数据?
09丨子查询:子查询的种类都有哪些,如何提高子查询的性能?
10丨常用的SQL标准有哪些,在SQL92中是如何使用连接的?
11丨SQL99是如何使用连接的,与SQL92的区别是什么?
12丨视图在SQL中的作用是什么,它是怎样工作的?
13丨什么是存储过程,在实际项目中用得多么?
14丨什么是事务处理,如何使用COMMIT和ROLLBACK进行操作?
15丨初识事务隔离:隔离的级别有哪些,它们都解决了哪些异常问题?
16丨游标:当我们需要逐条处理数据时,该怎么做?
17丨如何使用Python操作MySQL?
18丨SQLAlchemy:如何使用Python ORM框架来操作MySQL?
19丨基础篇总结:如何理解查询优化、通配符以及存储过程?
第二章:SQL性能优化篇 (18讲)
20丨当我们思考数据库调优的时候,都有哪些维度可以选择?
21丨范式设计:数据表的范式有哪些,3NF指的是什么?
22丨反范式设计:3NF有什么不足,为什么有时候需要反范式设计?
23丨索引的概览:用还是不用索引,这是一个问题
24丨索引的原理:我们为什么用B+树来做索引?
25丨Hash索引的底层原理是什么?
26丨索引的使用原则:如何通过索引让SQL查询效率最大化?
27丨从数据页的角度理解B+树查询
28丨从磁盘I/O的角度理解SQL查询的成本
29丨为什么没有理想的索引?
30丨锁:悲观锁和乐观锁是什么?
31丨为什么大部分RDBMS都会支持MVCC?
32丨查询优化器是如何工作的?
33丨如何使用性能分析工具定位SQL执行慢的原因?
34丨答疑篇:关于索引以及缓冲池的一些解惑
35丨数据库主从同步的作用是什么,如何解决数据不一致问题?
36丨数据库没有备份,没有使用Binlog的情况下,如何恢复数据?
37丨SQL注入:你的SQL是如何被注入的?
第三章:认识DBMS (7讲)
38丨如何在Excel中使用SQL语言?
39丨WebSQL:如何在H5中存储一个本地数据库?
40丨SQLite:为什么微信用SQLite存储聊天记录?
41丨初识Redis:Redis为什么会这么快?
42丨如何使用Redis来实现多用户抢票问题
43丨如何使用Redis搭建玩家排行榜?
44丨DBMS篇总结和答疑:用SQLite做词云
第四章:SQL项目实战 (3讲)
45丨数据清洗:如何使用SQL对数据进行清洗?
46丨数据集成:如何对各种数据库进行集成和转换?
47丨如何利用SQL对零售数据进行分析?
结束语 (1讲)
结束语 | 互联网的下半场是数据驱动的时代
SQL必知必会
登录|注册

08丨什么是SQL的聚集函数,如何利用它们汇总表的数据?

陈旸 2019-06-28
我们上节课讲到了 SQL 函数,包括算术函数、字符串函数、日期函数和转换函数。实际上 SQL 函数还有一种,叫做聚集函数,它是对一组数据进行汇总的函数,输入的是一组数据的集合,输出的是单个值。通常我们可以利用聚集函数汇总表的数据,如果稍微复杂一些,我们还需要先对数据做筛选,然后再进行聚集,比如先按照某个条件进行分组,对分组条件进行筛选,然后得到筛选后的分组的汇总信息。
有关今天的内容,你重点需要掌握以下几个方面:
聚集函数都有哪些,能否在一条 SELECT 语句中使用多个聚集函数;
如何对数据进行分组,并进行聚集统计;
如何使用 HAVING 过滤分组,HAVING 和 WHERE 的区别是什么。

聚集函数都有哪些

SQL 中的聚集函数一共包括 5 个,可以帮我们求某列的最大值、最小值和平均值等,它们分别是:
这些函数你可能已经接触过,我们再来简单复习一遍。我们继续使用 heros 数据表,对王者荣耀的英雄数据进行聚合。
如果我们想要查询最大生命值大于 6000 的英雄数量。
SQL:SELECT COUNT(*) FROM heros WHERE hp_max > 6000
运行结果为 41。
如果想要查询最大生命值大于 6000,且有次要定位的英雄数量,需要使用 COUNT 函数。
SQL:SELECT COUNT(role_assist) FROM heros WHERE hp_max > 6000
运行结果是 23。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《SQL必知必会》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(64)

  • grey927
    ORDER BY 是对分的组排序还是对分组中的记录排序呢?

    作者回复: 这是个好问题,ORDER BY就是对记录进行排序。如果你在前面用到了GROUP BY,实际上是一种分组的聚合方式,已经把一组的数据聚合成为了一条记录,所以再进行排序的时候,也相当于是对分的组进行排序。

    2019-07-04
    18
  • ack
    练习题
    1.SELECT COUNT(*) AS num,role_main,AVG(hp_max) FROM heros WHERE hp_max > 6000 GROUP BY role_main HAVING num>5 ORDER BY num DESC;
    2.SELECT COUNT(*) AS num,ROUND(MAX(hp_max+mp_max),2),ROUND(AVG(hp_max+mp_max),2),ROUND(MIN(hp_max+mp_max),2) FROM heros WHERE hp_max+mp_max > 7000 GROUP BY attack_range ORDER BY num DESC;

    作者回复: 正确

    2019-06-28
    1
    15
  • Amanda
    一个发现:虽然 SELECT 的执行顺序在 GROUP BY 和 HAVING 后面,但对于SELECT中列的别名都可以使用。
    MySQL中
    1. > SELECT COUNT(*) as num, role_main, AVG(hp_max) FROM heros
        -> WHERE hp_max>6000
        -> GROUP BY role_main
        -> HAVING COUNT(*)>5
        -> ORDER BY COUNT(*) DESC;
    +-----+-----------+-------------+
    | num | role_main | AVG(hp_max) |
    +-----+-----------+-------------+
    | 17 | 战士 | 7028 |
    | 10 | 坦克 | 8312.4 |
    | 6 | 法师 | 6417 |
    +-----+-----------+-------------+
    2. > SELECT COUNT(*) num, ROUND(AVG(hp_max+mp_max), 2) avg, ROUND(MAX(hp_max+mp_max), 2) max, ROUND(MIN(hp_max+mp_max), 2) min FROM heros
        -> WHERE (hp_max+mp_max)>7000
        -> GROUP BY attack_range
        -> ORDER BY num DESC;
    +-----+---------+----------+---------+
    | num | avg | max | min |
    +-----+---------+----------+---------+
    | 36 | 8654.42 | 11036.00 | 7117.00 |
    | 26 | 7743.77 | 8737.00 | 7025.00 |
    +-----+---------+----------+---------+

    作者回复: 在执行顺序上,SELECT字段在GROUP BY和HAVING之后,不过在SELECT字段之前,已经计算了聚集函数,也就是COUNT(*) as num。聚集函数的计算在GROUP BY之后,HAVING之前

    2019-06-28
    13
  • 安静的boy
    where先对数据进行排序,group by再进行分组。让我对数据筛选和分组恍然大悟!

    作者回复: 理解了HAVING和WHERE的区别,就了解了分组过滤和条件过滤。还有SELECT语句种的关键字的顺序:SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...

    2019-06-28
    3
  • 吃饭饭
    讲的很详细了,入门必备

    作者回复: 谢谢!

    2019-06-28
    2
  • mickey
    /*
    1.筛选最大生命值大于6000的英雄,按照主要定位进行分组,选择分组英雄数量大于5的分组,
    按照分组英雄数从高到低进行排序,并显示每个分组的英雄数量、主要定位和平均最大生命值。
    */
    SELECT count(*) as num, role_main, AVG(hp_max)
    FROM heros
    WHERE hp_max > 6000
    GROUP BY role_main
    HAVING num > 5
    ORDER BY num DESC

    num role_main AVG(hp_max)
    ------------------------------------
    17 战士 7028
    10 坦克 8312.4
    6 法师 6417

    /*
    2.筛选最大生命值与最大法力值之和大于7000的英雄,按照攻击范围来进行分组,
    显示分组的英雄数量,以及分组英雄的最大生命值与法力值之和的平均值、最大值和最小值,
    并按照分组英雄数从高到低进行排序,其中聚集函数的结果包括小数点后两位。
    */
    SELECT count(*) as num, ROUND(AVG(hp_max + mp_max), 2), MAX(hp_max + mp_max), MIN(hp_max + mp_max)
    FROM heros
    WHERE hp_max + mp_max > 7000
    GROUP BY attack_range
    HAVING num > 5
    ORDER BY num DESC

    num, ROUND(AVG(hp_max + mp_max), 2), MAX(hp_max + mp_max), MIN(hp_max + mp_max)
    ------------------------------------------------------------------------
    62 8272.53 11036 7025

    作者回复: SQL正确,最后结果贴的不太完整

    2019-06-28
    3
    2
  • Taozi
    练习2中反复出现的hp_max+mp_max可以绑定到一个变量吗?
    2019-06-28
    2
  • 圆子蛋
    1.SELECT COUNT(*) as num,role_main,AVG(hp_max) FROM heros WHERE hp_max > 6000 GROUP BY role_main HAVING num>5 ORDER BY num DESC;
    2.SELECT COUNT(*) as num,ROUND(MAX(hp_max+mp_max),2),ROUND(AVG(hp_max+mp_max),2),ROUND(MIN(hp_max+mp_max),2) FROM heros WHERE (hp_max+mp_max) > 7000 GROUP BY attack_range ORDER BY num DESC;
    老师在“如何对数据进行分组,并进行聚集统计”的第三个例子里,COUNT(*) 后面没有加 as num,但是 ORDER BY 里直接出现了 num?

    作者回复: COUNT(*)后面应该有 as num

    2019-06-28
    2
  • mickey
    有个错误:
    文中“比如,我们想要按照英雄的主要定位、次要定位进行分组,查看这些英雄的数量,并按照这些分组的英雄数量从高到低进行排序。”的SQL语句:SQL: SELECT COUNT(*), role_main, role_assist FROM heros GROUP BY role_main, role_assist ORDER BY num DESC

    在MySQL里会报错:[Err] 1054 - Unknown column 'num' in 'order clause'

    要改为:SELECT COUNT(*) as num, role_main, role_assist FROM heros GROUP BY role_main, role_assist ORDER BY num DESC;

    编辑回复: 您好,文章已进行更正,谢谢您的反馈。

    2019-06-28
    2
  • 峻铭
    前面老师在评论中回复过,在group by分组和having筛选分组之间还有一步使用聚集函数进行计算,在目前看到的having都是对cout聚集函数结果的筛选,想试试对其他聚集函数的筛选,然后对训练1做了点小改动:
    select count(*) as c,role_main,avg(hp_max) as v from heros where hp_max > 6000 GROUP BY role_main HAVING c > 5 and v > 7000 order by c DESC;
    2019-09-01
    1
  • bear
    Having 部分精彩,赞👍

    作者回复: 感谢

    2019-08-17
    1
  • supermouse
    思考题 1:
    SELECT
        COUNT(*) AS num, role_main, AVG(hp_max)
    FROM
        heros
    WHERE
        hp_max > 6000
    GROUP BY role_main
    HAVING num > 5
    ORDER BY num DESC;
    思考题 2:
    SELECT
        COUNT(*) AS num,
        attack_range,
        ROUND(AVG(hp_max + mp_max), 2),
        ROUND(MAX(hp_max + mp_max), 2),
        ROUND(MIN(hp_max + mp_max), 2)
    FROM
        heros
    WHERE
        hp_max + mp_max > 7000
    GROUP BY attack_range
    ORDER BY num DESC;

    作者回复: 正确

    2019-06-29
    1
  • 太精
    SELECT COUNT(*) AS num, role_main, AVG(hp_max) AS avg_max FROM heros WHERE hp_max > 6000 GROUP BY role_main HAVING num > 5 ORDER BY num DESC;
    SELECT ROUND((COUNT(*)),2) AS num, ROUND((AVG(hp_max+mp_max)),2) AS heros_avg, ROUND((MAX(hp_max+mp_max)),2) AS max_avg, ROUND((MIN(hp_max+mp_max)),2) AS min_avg FROM heros WHERE (hp_max+mp_max) > 7000 GROUP BY attack_range ORDER BY num desc;

    作者回复: 正确 不过COUNT(*)就不需要用ROUND了

    2019-06-28
    1
  • Geek_d3a509
    问题SQL:(1)SELECT COUNT(*) as num, role_main, avg(hp_max) FROM heros WHERE hp_max >6000 GROUP BY role_main HAVING num > 5 ORDER BY num DESC;

    (2)SELECT COUNT(*) as num, attack_range, ROUND(avg(hp_max + mp_max),2 ) as avg ,ROUND(MAX(hp_max + mp_max),2) as max, ROUND(MIN(hp_max + mp_max),2) as min FROM heros WHERE (hp_max + mp_max)>7000 GROUP BY attack_range ORDER BY num DESC;
    2019-12-11
  • Tony
    SELECT MIN(name), MAX(name) FROM heros;
    result:不知火舞,黄忠
    SELECT MIN(CONVERT(name USING gbk)), MAX(CONVERT(name USING gbk)) FROM heros
    result:阿珂,庄周
    这两条查出来的结果不一样?上面那个也不是a到z啊
    2019-12-03
  • Geek_f65511
    mysql: SELECT COUNT(*) as num, role_main, role_assist FROM heros WHERE hp_max > 6000 GROUP BY role_main, role_assist HAVING num > 5 ORDER BY num DESC;
    oracle: select count(*) as num,t.reson_code from E_STATE t where t.equi_code = 'R01' group by t.reson_code HAVING num > 5 order by num desc;

    在oracle下报错,锁num无效。是不是oracle下不支持having,但是不应该啊。
    2019-11-29
  • 丁丁历险记
    讲个段子 having 常用来做过滤掉那些跑来冒充程序员的人。
    他们深深的震惊了我的认知。
    2019-11-07
  • 扶幽
    作业:
    1) SELECT COUNT(*) AS num, role_main, AVG(hp_max) FROM heros WHERE hp_max>6000 GROUP BY role_main HAVING num>5 ORDER BY num DESC;
    2) SELECT COUNT(*) AS num, ROUND(AVG(hp_max+mp_max), 2) AS avg, ROUND(MAX(hp_max+mp_max),2) AS max, ROUND(MIN(hp_max+mp_max), 2) AS min FROM heros
    WHERE hp_max+mp_max>7000 GROUP BY attack_range ORDER BY num DESC;
    2019-10-26
  • Coool
    1、
    SELECT
        COUNT(*) AS num, role_main, AVG(hp_max)
    FROM
        heros
    WHERE hp_max>6000
    GROUP BY role_main
    HAVING num > 5
    ORDER BY num DESC
    2、
    SELECT
        COUNT(*) AS num, ROUND( AVG(hp_max+mp_max),2), ROUND( MAX(hp_max+mp_max),2), ROUND( MIN(hp_max+mp_max),2)
    FROM
        heros
    WHERE (hp_max+mp_max)>7000
    GROUP BY attack_range
    ORDER BY num DESC
    2019-10-18
  • whaleFall_
    1)
    SELECT COUNT(*) nums,role_main,AVG(hp_max) avg_hp
    from heros
    WHERE hp_max > 6000
    GROUP BY role_main
    HAVING nums > 5
    ORDER BY nums DESC

    2)SELECT COUNT(*) as nums,attack_range,ROUND(AVG(hp_max + mp_max),2) as avg_hp_mp,
    MAX(hp_max + mp_max) as max_hp_mp,
    MIN(hp_max + mp_max) as min_hp_mp
    FROM heros
    WHERE (hp_max + mp_max) > 7000
    GROUP BY attack_range
    ORDER BY nums DESC
    2019-10-17
收起评论
64
返回
顶部