- UNION(ALL)
- 联接查询
- INNER JOIN内连接
- 外连接(LEFT/RIGHT/FULL JOIN)
- 聚合函数
UNION(ALL)
将两个或更多个查询结果合并为单个结果集,该结果集包含联合查询中的所有查询的全部行
使用UNION
合并两个查询结果集的基本准则:
- 所有查询中的列数和列的顺序必须相同
- 数据类型必须兼容
ALL将全部行并入结果中,其中包括重复行。如果没有ALL则删除重复行
示例:
1 | -- 使用UNION合并两个学生表的学生信息 |
联接查询
根据数据库表之间的逻辑关系,从两个或多个数据库表中检索数据
联接查询需要满足的条件
所要连接的表必须拥有相同的字段值,且数据类型类似。尽量在表的主键上的基础上,指定连接条件
连接查询分类
- 内部链接:基本内连接,多表连接
- 外部连接:左外连接,右外连接,全外连接
- 交叉连接
INNER JOIN内连接
只返回两个表中连接字段相等的行,用...INNER JOIN...ON...
语句进行连接,JOIN
指定需要连接的数据表,ON
指定连接条件(INNER
可省略)
基本语法:
1 | SELECT 字段1,字段2,... |
示例:
1 | -- 查询学生信息及成绩 |
外连接(LEFT/RIGHT/FULL JOIN)
基本语法:
1 | USE 数据库名 |
左外连接
LEFT OUTER JOIN
以左表为基表,结果集返回左表的所有行,而右表只返回符合连接条件的记录,右表中不足的地方显示为NULL
示例:
1 | -- 查询所有学生信息及参加考试的学生成绩 |
右外连接
RIGHT OUTER JOIN
以右表为基表,结果集返回右表的所有行,而左表只返回符合连接条件的记录,左表中不足的地方显示为NULL
示例:
1 | -- 安徽查询所有课程信息及参加该考试的学生成绩 |
全外连接
FULL OUTER JOIN
结果集返回左表和右表的所有行
示例:
1 | -- 查找素有的学生信息及所有参加该考试的学生成绩 |
交叉连接(很少用)
CROSS JOIN
将从被连接的表中返回所有可能的记录组合(如:一个表8条记录,另一个表9条记录,结果将返回72条记录),交叉连接的结果集是量表行数乘积的集合,也被称为笛卡尔积
基本语法:
1 | USE 数据库名 |
注:交叉连接不需要使用ON连接条件
示例:
1 | SELECT ST.NAME,ST.AGE,ST.SEX,GR.SCORE FROM dbo.STUDENT ST CROSS JOIN dbo.GRADE GR |
聚合函数
SUM()
:计算表达式中所有值得和,忽略空值,这些表达式通常是字段名或包含字段名的表达式AVG()
:计算表达式的平均值,忽略空值,这些表达式通常是字段名或包含字段名的表达式COUNT(列名)
:计算表达式中非空值的数量,即忽略空值COUNT(*)
:计算表达式中所有值的数量,包括空值MIN()
:返回表达式中所有值的最小值,这些表达式通常是字段名或包含字段名的表达式MAX()
:返回表达式中所有值的最大值,这些表达式通常是字段名或包含字段名的表达式
SUM
示例:
1 | SELECT SUM(SCORE) FROM dbo.GRADE |
SUM(ALL|DISTINCT 列名)
返回表达式中所有值的和或仅非重复值的和。SUM
只能用于数字列,将忽略NULL
值。
ALL
表示所有值求和,默认是ALL
DISTINCT
表示对唯一值求和
SUM(列名) OVER(PARTITION BY 列名 ORDER BY 列名)
在SUM
后面使用OVER
子句可对表数据分区再求和,PARTITION BY
指定分区列,ORDER BY
指定在分区内按照某列的排序顺序在求和
示例:
1 | -- 对课程ID分区后对学生分数求和 |
AVG
示例:
1 | SELECT AVG(SCORE) FROM dbo.GRADE |
AVG(ALL|DISTINCT 列名)
返回组中各值得平均值,空值将被忽略,后面可以跟随OVER
子句
ALL
表示对所有值求平均值,默认是ALL
DISTINCT
表示对唯一值求平均值
AVG(列名) OVER(PARTITION BY 列名 ORDER BY 列名)
在AVG
使用OVER
子句可对表数据分区再求平均值,PARTITION BY
指定分区列,ORDER BY
指定在分区内按照某列排序再求平均值
示例:
1 | -- 对课程ID分区后对学生分数求平均值 |
COUNT
示例:
1 | SELECT COUNT(NAME) FROM dbo.STUDENT |
COUNT(ALL|DISTINCT 列名)
返回组中的项数,不包含空值
ALL
对所有值计数,不包括空值,默认是ALL
DISTINCT
计算唯一非空值数量
COUNT(列名) OVER(PARTITION BY 列名 ORDER BY 列名)
在COUNT
后使用OVER
子句可对表数据分区后计数,PARTITION BY
指定分区列,ORDER BY
指定在分区内按照某列排序再计数
示例:
1 | SELECT NAME,SEX,AGE,COUNT(NAME) OVER(PARTITION BY SEX) COUNT_PAR FROM dbo.STUDENT |
COUNT(*)返回表中的行数,包括空值和重复项
1 | SELECT COUNT(*) FROM dbo.STUDENT |
MIN
1 | SELECT MIN(AGE) FROM dbo.STUDENT |
MIN(列名)
返回族中最小的值,忽略空值
MIN(列名) OVER(PARTITION BY 列名 ORDER BY 列名)
在MIN
后使用OVER
子句可对表数据分区后求最小值,PARTITION BY
指定分区列,ORDER BY
指定在分区内按照某列排序在求最小值
示例:
1 | SELECT NAME,SEX,AGE,MIN(AGE) OVER(PARTITION BY SEX) MIN_PAR FROM dbo.STUDENT |
MAX
1 | SELECT MAX(AGE) FROM dbo.STUDENT |
MAX(列名)
返回族中最大的值,忽略空值
MAX(列名) OVER(PARTITION BY 列名 ORDER BY 列名)
在MAX
后使用OVER
子句可对表数据分区后求最大值,PARTITION BY
指定分区列,ORDER BY
指定在分区内按照某列排序在求最小值
示例:
1 | SELECT NAME,SEX,AGE,MAX(AGE) OVER(PARTITION BY SEX) MAX_PAR FROM dbo.STUDENT |
GROUP BY
GROUP BY
:对结果集分组,针对每一组返回一行
若SELECT
子句中同时包含聚合函数和GROUP BY
,则聚合函数对每个组聚合计算
若指定GROUP BT
时,GROUP BY
后的所有字段都要出现在SELECT
列表中
GROUP BY
后不能使用数据类型为text、ntext、image
的字段
示例:
1 | -- 简单GROUP BY示例 |
HAVING
使用HAVING
过滤分组后的数据,因此HAVING
要用在GROUP BY
之后
示例:
1 | -- 按照性别分区,求学生平均年龄 |
WHERE和HAVING区别
WHERE
语句在GROUP BY
语句之前,SQL
会在分组之前计算WHERE
语句HAVING
语句在GROUP BY
语句之后,SQL
会在分组之后计算HAVING
语句- 在一个
SQL
语句中可以同时有WHERE
子句和HAVING
子句,HAVING
与WHERE
子句类似,均用于设置限定条件 WHERE
子句的作用时在对查询结果进行分组前,将不符合WHERE
条件的行去掉,即在分组之前过滤数据,条件中不能包含聚合函数,使用WHERE
条件显示特定的行HAVING
子句的作用时筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚合函数,使用HAVING
条件显示特定的组,也可以使用多个分组标准进行分组
示例:
1 | -- 查询年龄大于11岁各性别学生平均年龄大于13岁的学生信息 |
ROLLUP、CUBE
在GROUP BY
后使用ROLLUP、CUBE
子句对分组数据汇总
ROLLUP
就是将GROUP BY
后面的第一个字段的各个值分组在聚合运算,而其他列并不要求,其中ROLLUP
包含仅使用GROUP BY
的结果集
而CUBE
则会将GROUP BY
后面的每一个字段的各个值分组在聚合运算,其中CUBE
结果集包含ROLLUP
结果集
注:ROLLUP、CUBE
在后续SQL SERVER版中将删除
示例:
1 | SELECT SEX,NAME,AVG(AGE) FROM dbo.STUDENT GROUP BY SEX,NAME WITH ROLLUP ORDER BY SEX,NAME |
子查询
在WHERE
子句中包含的SELECT
查询,就成为子查询或嵌套查询。而包含子查询的语句称为外部查询或外部选择。子查询可以嵌套在外部SELECT
、INSERT
、UPDATE
或DELETE
语句的WHERE
或HAVING
子句内,也可以嵌套在其他子查询内。
子查询类型:
- 使用
IN
或NOT IN
的子查询(用的比较多) - 使用
ANY
、SOME
或ALL
的子查询 - 使用
EXISTS
或NOT EXISTS
的子查询(用的比较多)
注:子查询通常用()括起来
使用IN或NOT IN的子查询
示例:
1 | -- 使用IN的子查询 |
联接总是可以表示为子查询,子查询经常(但不总是)可以表示为联接。这是因为联接时对称的,无论以何种顺序联接表A或B,都将得到相同的结果
使用联接而不是用子查询的一个同之处在于,联接使您可以在结果中显示多个表中的列
使用ANY、SOME或ALL的子查询
如果子查询的返回值不止一个,而是一个集合时,则不能直接使用比较运算符,可以在比较运算符和子查询之间插入ANY
或ALL
。ANY
与SOME
完全等效
ANY
任一个:
>ANY
:表示至少大于一个值,即大于最小值。因此>ANY(1,2,3)
表示大于1<ANY
:表示至少小于一个值,即小于最大值。因此<ANY(1,2,3)
表示小于3=ANY
:表示至少等于一个值,因此=ANY(1,2,3)
表示等于1或等于2或等于3,=ANY
等效于IN
ALL
所有:
>ALL
:表示大于每一个值,即大于最大值。因此>ALL(1,2,3)
表示大于3<ALL
:表示小于每一个值,即小于最小值。因此<ALL(1,2,3)
表示小于1
示例:
1 | -- 使用ANY的子查询 |
使用EXISTS或NOT EXISTS的子查询
使用EXISTS
的子查询,只进行存在测试,外部查询的WHERE
子句测试子查询返回的行是否存在,子查询实际上不产生任何数据,它时返回TRUE
或FALSE
值
使用EXISTS
引入的子查询的语法:
1 | WHERE [NOT] EXISTS (subquery) |
EXISTS
关键字前面没有列名、常量或其他表达式- 由
EXISTS
引入的子查询的选择列通常几乎都是由星号(*)
组成,由于这是测试是否存在符合子查询指定条件的行,因此不必列出列名
示例:
1 | -- 使用EXISTS的子查询 |
在UPDATE、DELETE和INSERT中使用子查询
示例:
1 | -- 在DELETE语句中使用NOT IN子查询 |
使用嵌套查询返回特定排名的数据
示例:
1 | -- 查询成绩表中排名名词在中间的信息和成绩 |
不用聚合函数求最大值
示例:
1 | -- 使用聚合函数求学生最大年龄 |