SQL 查询之集合运算 & 聚合函数

 

1、集合运算

在数学中,不仅可以对指定的数字个体做四则运算,还可以对指定的集合整体做交并补运算。类似的,在数据库中也是不仅可以对具体的数据行进行增删改查,还可以对查询结果集进行集合运算。SQL Server 中的集合运算有并集运算、差集运算和交集运算三种,本节将逐一讲述。

1.1、并集运算 UNION

并集运算符 UNION 的作用是将两个或多个查询的结果集合并为单个结果集。在 UNION 运算中,需要确保各个子结果集的字段数相同、字段的顺序相同、字段的数据类型兼容。合并结果集的列名始终会取第一个子结果集中的列名,因此,如果要对合并结果集排序,则需要用第一个子结果集的字段名。

参数 ALL 表示将全部行并入结果集中,换句话说合并结果集可能会包含重复行;相反,如果未指定该参数,则会删除重复行。需要注意的是,在做重复判断时,UNION 会把两个 NULL 值被视为相等的。因为 UNION ALL 不需要删除重复行,所以性能比 UNION 要好。因此,除非必须要删除重复行,否则建议一律使用 UNION ALL。

1.1.1、简单 UNION ALL。查询 1 班的男生和 2 班的女生。示例如下:

SELECT * FROM T_Students t1 WHERE t1.ClassId = 1 AND t1.Gender = 1
UNION ALL
SELECT * FROM T_Students t2 WHERE t2.ClassId = 2 AND t2.Gender = 0;

1.1.2、简单 UNION ALL。查询 1 班的男生和该班的男生人数。示例如下:

SELECT 1 cnt,t1.Code,t1.Name FROM T_Students t1 WHERE t1.ClassId = 1 AND t1.Gender = 1
UNION ALL
SELECT COUNT(1),NULL,NULL FROM T_Students t2 WHERE t2.ClassId = 1 AND t2.Gender = 1;

查询结果如下:

cnt         Code                           Name
----------- ------------------------------ ------------------------------
1 S330102001 郑强
1 S330102002 肖俊生
1 S330300007 钱波
1 S330104009 金桥
4 NULL NULL

1.1.3、UNION 与 ORDER BY。查询 1 班的男生和 2 班的女生,并且将最终结果集按年龄从大到小排序。示例如下:

SELECT * FROM T_Students t1 WHERE t1.ClassId = 1 AND t1.Gender = 1
UNION ALL
SELECT * FROM T_Students t2 WHERE t2.ClassId = 2 AND t2.Gender = 0
ORDER BY t1.Birthday;

1.1.4、UNION 与 SELECT INTO。创建一个活动学生表,并将 1 班的男生和 2 班的女生加入其中。示例如下:

SELECT t1.Code,t1.Name,t1.Gender,t1.Birthday
INTO T_ActivityStudents
FROM T_Students t1
WHERE t1.ClassId = 1 AND t1.Gender=1
UNION ALL
SELECT t2.Code,t2.Name,t2.Gender,t2.Birthday
FROM T_Students t2
WHERE t2.ClassId = 2 AND t2.Gender=0;

1.1.5、通过括号来改变 UNION 的运算顺序。示例如下:

WITH t AS(
SELECT TOP(3) * FROM T_Students t WHERE t.ClassId = 1 ORDER BY t.Birthday
)
SELECT * FROM t
UNION ALL(
SELECT * FROM t
UNION
SELECT * FROM t
);

简单说明一下:首先,上例会返回 6 条数据。其次,很明显 CTE 中包含了年龄最大的 3 个学生。然后,括号会提升运算符的优先级,而且 UNION 会删除重复行,所以括号中会返回 3 条数据。最后,UNION ALL 不会删除重复行,所以最终返回的 6 条数据是第一个查询返回的 3 条数据加上括号中两个查询共同产生的 3 条数据。

1.2、差集运算 EXCEPT

差集运算符 EXCEPT 的作用是比较两个查询的结果集,然后返回左侧结果集包含但右侧结果集不包含的行,且不包含重复行。与 UNION 运算相同,EXCEPT 运算也要求各个子结果集的字段数相同、顺序相同、类型兼容。且 EXCEPT 也会把两个 NULL 值被视为相等的。示例如下:

SELECT * FROM T_GoodStudents t1 WHERE t1.Gender = 0
EXCEPT
SELECT * FROM T_GoodStudents t2 WHERE t2.Birthday < '2000-01-01';

注意:上例是用女生这个结果集减去非 00 后学生结果集,但得到的结果集并不一定是 00 后女生,因为女生的出生日期可能是 NULL,所以最终的结果集是 00 后女生加上出生日期为 NULL 的女生。

类似于 UNION:EXCEPT 也可以与 ORDER BY 连用来给差集(最终的结果集)排序,而且差集的列名也跟第一个子结果集的列名相同。EXCEPT 还可以与 SELECT INTO 连用将差集拷贝到一个新表中。当有多个 EXCEPT 时也可以通过括号来改变运算顺序。具体用法可参考 UNION 的示例。

1.3、交集运算 INTERSECT

交集运算符 INTERSECT 的作用是比较两个查询的结果集,然后返回左侧结果集和右侧结果集都包含的行,且不包含重复行。与 UNION 运算相同,INTERSECT 运算也要求各个子结果集的字段数相同、顺序相同、类型兼容。且 INTERSECT 也会把两个 NULL 值被视为相等的。示例如下:

SELECT * FROM T_GoodStudents t1 WHERE t1.Gender = 0
INTERSECT
SELECT * FROM T_GoodStudents t2 WHERE t2.Birthday < '2000-01-01';

注意:上例是取女生这个结果集和非 00 后学生结果集的交集,但得到的结果集并不一定是非 00 后女生,因为女生的出生日期可能是 NULL,所以最终的结果集是非 00 后女生加上出生日期为 NULL 的女生。

类似于 UNION:INTERSECT 也可以与 ORDER BY 连用来给交集(最终的结果集)排序,而且交集的列名也跟第一个子结果集的列名相同。INTERSECT 还可以与 SELECT INTO 连用将交集拷贝到一个新表中。当有多个 INTERSECT 时也可以通过括号来改变运算顺序。具体用法可参考 UNION 的示例。

1.4、集合运算小结

上文逐一讲述了各个集合运算符的语法和用途。其实这些集合运算符不仅可以单独使用,还可以结合起来使用,示例如下:

SELECT t1.Id,t1.Name,t1.Gender,t1.Birthday FROM T_Students t1 WHERE t1.ClassId = 1
UNION ALL
SELECT t2.Id,t2.Name,t2.Gender,t2.Birthday FROM T_Students t2 WHERE t2.ClassId = 3
EXCEPT
SELECT * FROM T_GoodStudents t3 WHERE t3.Birthday < '2000-01-01'
INTERSECT
SELECT * FROM T_GoodStudents t4 WHERE t4.Gender = 1;

注意:上例的运算顺序并不是先 UNION ALL,然后 EXCEPT,再 INTERSECT。因为 INTERSECT 比 EXCEPT 和 UNION 的优先级要高,而 EXCEPT 与 UNION 的优先级相同,所以上例的实际运算顺序是先 INTERSECT,然后 UNION ALL,最后再用 UNION ALL 的结果集减 INTERSECT 的结果集,即最后进行 EXCEPT 运算。

2、聚合函数

聚合函数的作用是对一组值执行计算,并返回单个结果值。聚合函数只能在 SELECT 子句或 HAVING 子句中作为表达式来用。求行数函数 COUNT、求和函数 SUM、求最大值函数 MAX、求最小值函数 MIN、求平均值函数 AVG,这 5 个函数是最常用的聚合函数,主流的关系型数据库也都支持它们。

其实常见的关系型数据库都支持很多聚合函数,但其中大部分都是非标准的,各个数据库之间的差别也比较大,而且这些函数也都不常用。个人建议实际工作中不要用这些函数,以免跟某个具体的数据库绑死。

2.1、求行数函数 COUNT

求行数函数 COUNT 会返回查询结果集的行数。COUNT 函数中可以是一个具体的列,也可以是代表所有列的星号,还可以是一个具体的常量或变量。示例如下:

SELECT COUNT(t.Id) result FROM T_Students t; -- result:32 rows
SELECT COUNT(*) result FROM T_Students t; -- result:32 rows
SELECT COUNT(1) result FROM T_Students t; -- result:32 rows

COUNT 是所有聚合函数中唯一不会忽略 NULL 值的函数,但如果被计算列本身含有 NULL 值是会被忽略的。示例如下:

SELECT COUNT(Remark) result FROM T_Students t; -- result:28 rows

在 COUNT 函数中添加 DISTINCT 参数,表示会先去除重复行,然后统计剩下的非 NULL 且唯一的值的个数。示例如下:

SELECT COUNT(DISTINCT Remark) result FROM T_Students t; -- result:26 rows

注意:COUNT 函数的返回值一定是大于或等于 0 的整数,证明如下:

SELECT COUNT(*) result;             -- result:1 rows
SELECT COUNT(*) result WHERE 1 = 2; -- result:0 rows

另外,从 SQL Server 2008 开始,官方在增加了一个COUNT_BIG函数,它的用法和用途与 COUNT 完全相同,唯一不同的就是返回值的类型。COUNT 函数总是返回一个 INT 类型的整数,而COUNT_BIG函数总是返回一个 BIGINT 类型的整数。示例如下:

SELECT COUNT_BIG(1) result FROM T_Students t;               -- result:32 rows
SELECT COUNT_BIG(Remark) result FROM T_Students t; -- result:28 rows
SELECT COUNT_BIG(DISTINCT Remark) result FROM T_Students t; -- result:26 rows

2.2、求和函数 SUM

求和函数 SUM 会返回表达式中所有值的和。SUM 函数会忽略所有 NULL 值,且只能应用于数字类型的字段。例如要查询学生 1 第 1 次考试的总分,示例如下:

SELECT SUM(t.Scores) FROM T_ExamResults t WHERE t.StudentId = 1 AND t.Counts = 1;

在 SUM 函数中添加 DISTINCT 参数,表示会先去除重复行,然后统计剩下的非 NULL 且唯一的数值之和。示例如下:

SELECT SUM(t.Scores) result FROM T_ExamResults t WHERE t.StudentId = 6;          -- result:2202.5
SELECT SUM(DISTINCT t.Scores) result FROM T_ExamResults t WHERE t.StudentId = 6; -- result:1857.5

注意:SUM 函数的返回值有可能会是 NULL 值,证明如下:

SELECT SUM(1) result;             -- result:1
SELECT SUM(1) result WHERE 1 = 2; -- result:NULL

2.3、求最大值函数 MAX

求最大值函数 MAX 会返回表达式中的最大值。MAX 函数会忽略所有 NULL 值。例如要查询学生 1 课程 1 的历次考试最高分,示例如下:

SELECT MAX(t.Scores) FROM T_ExamResults t WHERE t.StudentId = 1 AND t.Counts = 1;

MAX 函数还可以作用于日期类型或字符类型,此时 MAX 将按照日期数值或字符排序顺序来确定最大值。示例如下:

SELECT MAX(t.Birthday) FROM T_Students t; -- 数值最大的出生日期,年龄最小
SELECT MAX(t.Name) FROM T_Students t; -- 字符排序最靠后的姓名

注意:MAX 函数的返回值有可能会是 NULL 值,证明如下:

SELECT MAX(1) result;             -- result:1
SELECT MAX(1) result WHERE 1 = 2; -- result:NULL

2.4、求最小值函数 MIN

求最小值函数 MIN 会返回表达式中的最小值。MIN 函数会忽略所有 NULL 值。例如要查询学生 1 课程 1 的历次考试最低分,示例如下:

SELECT MIN(t.Scores) FROM T_ExamResults t WHERE t.StudentId = 1 AND t.Counts = 1;

MIN 函数还可以作用于日期类型或字符类型,此时 MAX 将按照日期数值或字符排序顺序来确定最小值。示例如下:

SELECT MIN(t.Birthday) FROM T_Students t; -- 数值最小的出生日期,年龄最大
SELECT MIN(t.Name) FROM T_Students t; -- 字符排序最靠前的姓名

注意:MIN 函数的返回值有可能会是 NULL 值,证明如下:

SELECT MIN(1) result;             -- result:1
SELECT MIN(1) result WHERE 1 = 2; -- result:NULL

2.5、求平均值函数 AVG

求平均值函数 AVG 会返回表达式中所有值的平均值。AVG 函数会忽略所有 NULL 值,且只能应用于数字类型的字段。例如要查询学生 1 第 1 次考试的平均分,示例如下:

SELECT AVG(t.Scores) FROM T_ExamResults t WHERE t.StudentId = 1 AND t.Counts = 1;

在 AVG 函数中添加 DISTINCT 参数,表示会先去除重复行,然后统计剩下的非 NULL 且唯一的数值之和。示例如下:

SELECT AVG(t.Scores) result FROM T_ExamResults t WHERE t.StudentId = 6;          -- result:73.416666
SELECT AVG(DISTINCT t.Scores) result FROM T_ExamResults t WHERE t.StudentId = 6; -- result:74.300000

注意:AVG 函数的返回值有可能会是 NULL 值,证明如下:

SELECT AVG(1) result;             -- result:1
SELECT AVG(1) result WHERE 1 = 2; -- result:NULL

2.6、聚合函数小结

上文逐一讲述了常见五大聚合函数的基本语法和用途。其实这些聚合函数不仅可以单独使用,还可以结合起来使用。

示例一、查询第 1 次课程 2 考试成绩的统计结果:

SELECT COUNT(1) 参与人数,
SUM(t.Scores) 总分,MAX(t.Scores) 最高分,MIN(t.Scores) 最低分,AVG(t.Scores) 平均分
FROM T_ExamResults t
WHERE t.Counts = 1 AND t.CourseId = 2;

示例二、查询 1 班的学生总数及年龄统计结果:

WITH t AS(
SELECT t.Code,t.Name,DATEDIFF(YEAR,t.Birthday,GETDATE()) Age
FROM T_Students t
WHERE t.ClassId = 1
)
SELECT COUNT(1) 学生个数,MAX(t.Age) 最大年龄,MIN(t.Age) 最小年龄,AVG(t.Age) 平均年龄
FROM t;

注意:本文所有关于聚合函数的示例,查询选择列表中包含的都是聚合函数表达式,没有一个字段,因为不允许,不过倒是可以包含与表字段无关的常量或变量。其实聚合函数通常与 GROUP BY 子句一起使用,而且也只有包含在 GROUP BY 子句中的字段才能出现在查询选择列表中,具体原因将在下一篇博文中具体讲述。

3、本文小结

本文主要讲述了 SQL Server 中的集合运算和聚合函数,以及它们的基本语法和用途。在集合运算中,UNION 和 UNION ALL 是比较常用的。而常见的 5 个聚合函数都比较常用。

本文参考链接:

去导航目录篇下载创建本系列博文通用库表及数据的 SQL 语句

本文链接http://www.cnblogs.com/hanzongze/p/tsql-aggregate.html

集合运算 & 聚合函数的更多相关文章

  1. SQL Server温故系列(4):SQL 查询之集合运算 & 聚合函数

    1.集合运算 1.1.并集运算 UNION 1.2.差集运算 EXCEPT 1.3.交集运算 INTERSECT 1.4.集合运算小结 2.聚合函数 2.1.求行数函数 COUNT 2.2.求和函数 ...

  2. Matlab的集合运算[转]

    今天遇到一个问题:有向量a和向量b,b是a的子向量(元素全部来自a),求向量a去掉向量b后剩下的元素构成的向量. 这么一个简单的问题,搜了半天也没有得到结果,因为找不到合适的关键词来描述这个问题. 在 ...

  3. Oracle组函数、多表查询、集合运算、数据库对象(序列、视图、约束、索引、同义词)等

    count组函数:(过滤掉空的字段) select count(address),count(*) from b_user max() avg() min(),sum() select sum(age ...

  4. 5_PHP数组_3_数组处理函数及其应用_9_数组集合运算函数

    以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 数组集合运算函数 1. array_merge() 函数 程序: <?php $array1 = array ...

  5. [SQL] SQL 基础知识梳理(七)- 集合运算

    SQL 基础知识梳理(七)- 集合运算 目录 表的加减法 联结(以列为单位) 一.表的加减法 1.集合:记录的集合(表.视图和查询的执行结果). 2.UNION(并集):表的加法 -- DDL:创建表 ...

  6. 第17课-数据库开发及ado.net 聚合函数,模糊查询like,通配符.空值处理.order by排序.分组group by-having.类型转换-cast,Convert.union all; Select 列 into 新表;字符串函数;日期函数

    第17课-数据库开发及ado.net 聚合函数,模糊查询like,通配符.空值处理.order by排序.分组group by-having.类型转换-cast,Convert.union all;  ...

  7. orm中的聚合函数,分组,F/Q查询,字段类,事务

    目录 一.聚合函数 1. 基础语法 2. Max Min Sum Avg Count用法 (1) Max()/Min() (2)Avg() (3)Count() (4)聚合函数联用 二.分组查询 1. ...

  8. SQL之开窗函数详解--可代替聚合函数使用

    在没学习开窗函数之前,我们都知道,用了分组之后,查询字段就只能是分组字段和聚合的字段,这带来了极大的不方便,有时我们查询时需要分组,又需要查询不分组的字段,每次都要又到子查询,这样显得sql语句复杂难 ...

  9. Task04:集合运算

    4.1 表的加减法 4.1.1 什么是集合运算 集合在数学领域表示"各种各样的事物的总和", 在数据库领域表示记录的集合. 具体来说,表.视图和查询的执行结果都是记录的集合, 其中 ...

随机推荐

  1. 机器学习实战(1)- KNN

    KNN:k近邻算法-在训练样本中找到与待测样本距离相近的N个样本,并用这N个样本中所属概率最大的类别作为待测样本的类别. 算法步骤: 1.对训练中的样本数据的不同属性进行归一化处理. 2.计算待测样本 ...

  2. jquery选择器(1)

    jQuery 元素选择器 jQuery 使用 CSS 选择器来选取 HTML 元素. $("p") 选取 <p> 元素. $("p.intro") ...

  3. 页面截取字段和转码,页面截取字段时候需要进入JS

    截取字段    ${fn:substring(info.cpflmc,0,20)}${fn:length(info.cpflmc)>40?'...':''}             表头list ...

  4. 为什么要监控sql语句,以及如何监控,都有哪几种方式可以监控。

    快速阅读 为什么要监控sql语句,以及如何监控,都有哪几种方式可以监控. 我们知道sql server 中有个工具叫sql profile ,可以实时监控sql server中 执行的sql 语句,以 ...

  5. JavaWeb之Tomcat(1) —— Tomcat的目录结构

    1. bin 文件夹 存放Tomcat的可执行文件 (1) startup.bat 文件,启动Tomcat服务的批处理文件. (2) shutdown.bat 文件,结束Tomcat服务的批处理文件. ...

  6. NGUI: Next-Gen UI 2018.3.0f

    https://assetstore.unity.com/packages/tools/gui/ngui-next-gen-ui-2413 NGUI is a very powerful UI sys ...

  7. android x86 安装

    1.下载页面 http://www.android-x86.org 下载了: android-x86-8.1-r2.iso 用Win32DiskImager制作usb启动盘. 参考: https:// ...

  8. CNS、ENS和PNS的发育过程

    central nervous system (CNS) peripheral nervous system (PNS) enteric nervous system (ENS) 做这部分的科研必须要 ...

  9. linux postgresql

  10. Variance Inflation Factor (VIF) 方差膨胀因子解释_附python脚本

    python信用评分卡(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_camp ...