数据库原理及应用_数据库基础_第2章关系数据库标准语言SQL_数据查询(2)分组查询
前言
"<数据库原理及应用>(MySQL版)".以下称为"本书"中2.3.2节
2.3.2分组查询
分组的概念
本书P52没有给出分组的定义(这本书部分内容比较乱),笔者尝试给出分组的定义:以属性为分组依据,若表中某一列中有着相同的属性值,则他们对应的元组属于同一分组.假设有下面一张表
序号 | surname | second_name | grade | score |
1 | 赵 | 大 | 1 | 91 |
2 | 赵 | 二 | 1 | 92 |
3 | 钱 | 大 | 1 | 93 |
4 | 钱 | 二 | 2 | 96 |
有赵大,赵二,钱大,钱二共4人,他们分别就读于1年级和2年级.
若以surname(姓氏)分组,则元组1和元组2属于一组,共同特点都姓赵;同理元组3和元组4属于另一组
若以second_name(名)分组,则元组1和元组3属于一组,元组2和元组4属于一组.
若以grade(年级)分组,则元组1,2,3属于一组.元组4属于另一分组
注意:使用者可以根据需要设定分组,所以上面的黑体字概念并不完全准确,.例如:
WHERE score BETWEEN 0 AND100;只要score不是空(NULL),那么一整张表都属于一个分组.
聚合函数
概念
聚合函数的概念:对分组内的某个列(属性)按照一定方法统计,得出1个结果.
什么情况下使用聚合函数?聚合函数的使用有两个方面需注意:
1.属性的数据类型是可以被统计的,综合前面的知识,属性的数据类型是数值型或者时间型,而非字符串型时,视为可被统计.以上表为例,不会去使用聚合函数SUM(surname).
2属性的计算是有意义的.以上面的表为例,聚合函数用在属性score上,SUM(score)表示分组内人员的总分,AVG(score)平均分,MAX(score)最大分数,MIN(score)最小分数,这是存在具体意义的.而如果把聚合函数用在属性grade上,用AVG(grade)表示几个人所在的平均年级?显然是没有意义的,也不会这样用
聚合函数的使用条件是:属性可被计算(数值型或时间型数据类型)且计算存在意义.
聚合函数使用规则
本书P53:聚合函数只能用于查询列(属性),ORDER BY子句和HAVING子句.
count(*)外的所有聚合函数忽略NULL(空)的统计.
---聚合函数忽略NULL的统计,所以0和NULL是不一样的.如果上面的score有1个是0分,结果填NULL,那么平均分计算出来结果不一样.由此推导出属性值的数据类型是数值型的,必须填.
表和分组
从上面的内容,大概知道了什么是分组,可以对分组的某些属性进行统计.接下来面临的问题是如何在查询中使用分组.此时笔者觉得应该对表和分组的关系做一点深入理解.
稍加思考就能想到:表是天然分组的,属性是分组的依据,相同属性值的元组自动分为一组.
使用分组
使用分组是分组查询中最重要的内容,他决定了在表的"纵向"选择出满足要求的元组(与之对应的是SELECT子句在"横向"选择出满足需求的属性,两者结合得到满足需求的表)
1>使用WHERE子句指定具体分组
表是二维的,通过SELECT语句查询列,用指定分组查询行(元组),查询到需要的表.具体操作方法参看本书P53例2-23.
WHERE deptno=30; //查询所有deptno=30的元组
如果把部门号为20的分组查询出来
WHERE deptno=20 AND deptno=30 ; //查询所有deptno=20和deptno=30的元组
2>GROUP BY子句
表示以某一个或多个属性为分组依据查询.如果以1个属性为分组依据,则称为单列分组,以多个属性为分组依据,则称为多列分组.示例分别见本书P53例2-24(单列分组)和P54例2-25(多列分组)
HAVING子句
HAVING子句和GROUP BY子句配套使用,表示在查询的组中选择符合条件的组.
3>WHERE和GROUP BY联合使用
见本书P54例2-26.WHERE做出第1层限制,GROUP BY在此基础上搜出结果(组),再由HAVING限制得到结果(结果仍是组的形式).这个例子很典型,对查找条件的设置同时使用了where和having.
抽象理解
一个人是否变聪明,时常查看自己的抽象能力.笔者将不定期在帖子中增加抽象理解板块
WHERE分组
WHERE体现的思想是"任意分组".设置条件表达式,可以使用WHERE查询出任意一个元组(行)或者任意多个元组(行).表达出WHERE可以选择或者排除任意的元组
GROUP BY子句&HAVING子句
GROUP BY体现的思想是"使用固定分组".这里的固定分组如前所述由"某些元组拥有共同的属性值"带来.同时表默认被划分为若干分组.
GROUP BY的另一个思想:"默认搜索结果将包含表中所有元组"(在未加WHERE和HAVING限制的条件下).而与之对应的HAVING子句的思想是"限制GROUP BY的搜索结果"
查询,基本查询和分组查询
想象一下:
查询select是从一张表中抽出一部分列组成的另一张表---去掉某些列,所有行(元组)保留
基本查询有了where做条件限制,去掉了某些行---相对于"查询"少了一些行
分组查询:所有的行(元组)被划分为若干组,其中某些组被选中组成一张表
分组查询的使用场景
表是天然分组的,当查询需求中出现"每"或者"各"的时候,表示要使用分组查询
多读几次例子也能体会到.
小结
分组查询的一些理解
抽象理解的引入