聚合函数
COUNT(*)议计算元组的个数
COUNT(列名) 对一列中的值计算个数,这里涉及到列名唯一(DISTINCT)
SUM(列名) 求某一列值的总和(此列的值必须是数值型)
AVG(列名) 求某一列值的平均值(此列的值必须是数值型)
MAX(列名) 求某一列值的最大值
MIN(列名) 求某一列值的最小值
SELECT语句完整的句法
SELECT语句完整的句法如下:
SELECT 目标表的列名或列表达式序列
FROM 基本表名和(或)视图序列
[ WHERE 行条件表达式 ]
[ GROUP BY 列名序列
[ HAVING 组条件表达式 ]]
[ ORDER BY 列名[ ASC|DESC ],… ]
整个语句的执行过程如下:
(1)读取FROM子句中基本表、视图的数据,执行笛卡尔积操作。
(2)选取满足WHERE子句中给出的条件表达式的元组。
(3)按GROUP子句中指定列的值分组,同时提取满足HAVING子句中组条件表达式的那些组。
(4)按SELECT子句中给出的列名或列表达式求值输出。
(5)ORDER子句对输出的目标表进行排序,按附加说明ASC升序排列,或按DESC降序排列。(默认值为ASC)
例3.11 对教学数据库的基本表S、SC、C中数据进行查询和计算。
①统计每一年龄选修课程的学生人数
SELECT AGE,COUNT(DISTINCT S.S#)
FROM S,SC
WHERE S.S#=SC.S#
GROUP BY AGE
由于要统计每一个年龄的学生人数,因此要把满足WHERE子句中条件的查询结果按年龄分组,在每一组中的学生年龄相同。此时的SELECT子句应对每一组分开进行操作,在每一组中,年龄只有一个值,统计的人数是这一组中的学生人数。
注:出现聚合函数就要用GROUP BY子句。
②求基本表S中男同学的每一年龄组(超过50人)有多少人?要求查询结果按人数升序排列,人数相同按年龄降序排列。
SELECT AGE,COUNT(S#) FROM S
WHERE SEX='M'
GROUP BY AGE
HAVING COUNT(*)> 50
ORDER BY 2,AGE DESC;
SELECT语句中的限定
SELECT子句中的规定SELECT子句描述查询输出的表格结构,即输出值的列名或表达式。其形式如下:
SELECT [ ALL|DISTINCT ] <列名或列表达式序列> | *
1)DISTINCT选项保证重复的行将从结果中去除;而ALL选项是默认的,将保证重复的行留在结果中,一般就不必写出。
2)星号*是对在FROM子句中命名表的所有列的简写。
3)列表达式是对一个单列求聚合值的表达式。
4)允许表达式中出现包含+、-、*和/以及列名、常数的算术表达式。
例3.12 对基本表S、SC、C进行查询
1)在基本表SC中检索男同学选修的课程号
SELECT DISTINCT C# FROM S,SC WHERE S.S#=SC.S# AND SEX='M'
2)检索每个学生的出生年份
SELECT S#,SNAME,2008-AGE FROM S
条件表达式中的算术比较操作条件表达式中可出现算术比较运算符(<,<=,>,>=,=,!=),也可以用“BETWEEN … AND …”比较运算符限定一个值的范围。
例3.13 在基本表S中检索18~20岁的学生姓名,可用下列语句实现
1)SELECT SNAME FROM S WHERE AGE>=18 AND AGE<=20
2) SELECT SNAME FROM S WHERE AGE BETWEEN 18 AND 20
不在某个范围内可以用“NOT BETWEEN … AND …”比较运算符
列和基本表的改名操作用“旧名 AS 新名”或 “旧名 新名”形式
例3.14 在基本表S中检索每个学生的出生年份,输出的列名为STUDENT_NAME 和 BIRTH_YEAR
SELECT SNAME STUDENT_NAME,2008-AGE AS BIRTH_YEAR FROM S
字符串的匹配操作(LIKE、NOT LIKE)条件表达式中字符串匹配操作符是“LIKE”。在表达式中可使用两个通配符:
百分号(%):与零个或多个字符组成的字符串匹配。
下划线(_):与单个字符匹配。
在基本表S中检索姓名以字符D打头的学生姓名。
SELECT SNAME FROM S WHERE SNAME LIKE 'D%‘
在“LIKE”表达式中使用“ESCAPE”关键字来定义转义字符
例:如果使用反斜线(\)作为转义符
LIKE‘ab\%cd%’ESCAPE ‘\’ 匹配所有以” ab%cd”开头的字符串
LIKE ‘ab\\cd%’ESCAPE ‘\’匹配所有以”ab\cd”开头的字符串
集合的并、交、差操作当两个子查询结果的结构完全一致时,可以让这两个子查询执行并、交、差操作。并、交、差的运算符为UNION、INTERSECT和EXCEPT。
“θSOME”操作表示左边那个元组与右边集合中至少一个元素满足θ运算。“θALL”操作表示左边那个元组与右边集合中每一个元素满足θ运算。
例3.18
①检索学习C2课程的学号与姓名
SELECT S#,SNAME FROM S
WHERE S#=SOME(SELECT S# FROM SC WHERE C#='C2')
注意:IN与“=SOME”等价,但“NOT IN ”不等价于“<>SOME”
②检索至少有一门成绩超过学生S4一门成绩的学生学号。
SELECT DISTINCT S# FROM SC
WHERE GRADE>SOME(SELECT GRADE FROM SC WHERE S#='S4')
③检索不学C2课程的学生姓名与年龄。
SELECT SNAME,AGE FROM S
WHERE S#<>ALL(SELECT S# FROM SC WHERE C#='C2')
注:NOT IN 与<>ALL等价
④检索平均成绩最高的学生学号
SELECT S# FROM SC
GROUP BY S# HAVING AVG(GRADE)>=ALL(SELECT AVG(GRADE) FROM SC GROUP BY S#)
在SQL中,不允许对聚合函数进行复合运算,因此不能写成SELECT MAX(AVG(GRADE) 形式
导出表的使用SQL2允许在FROM子句中使用子查询。如果在FROM子句中使用了子查询,那么要给子查询的结果起个表名和相应的列名。
例3.20 在表SC中检索平均成绩超过80分的学生学号和平均成绩
SELECT S#,AVG(GRADE) FROM SC
GROUP BY S# HAVING AVG(GRADE)>80
此查询还可以与成下面的形式:
SELECT S#,AVG_GRADE
FROM (SELECT S#,AVG(GRADE) FROM SC GROUP BY S#) AS RESULT(S#,AVG_GRADE)
WHERE AVG_GRADE>80
l
仼?