赞
踩
SELECT [ ALL | DISTINCT ] <目标列表达式> [,<目标列表达式>] ...
FROM <表名或视图名> [,<表名或视图名> … ] | (<SELECT语句>) [AS] <别名>
[ WHERE <条件表达式> ]
[ GROUP BY <列名1> [ HAVING <条件表达式>] ]
[ ORDER BY <列名2> [ ASC | DESC ] ] ;
SELECT <列名> [AS] <别名>
例如:将表达式 2020-Sage 取别名为 BIRTHDAY
SELECT 2020-Sage BIRTHDAY
SELECT DISTINCT <列名>
例如:消除在查询时候重复出现的 Sno
SELECT DISTINCT Sno
BETWEEN “A” AND “B” --其范围就是[ A, B ];
NOT BETWEEN “A” AND “B” --其范围就是( -∞, A ) ∩ ( B, +∞ );
比如: 查询年龄在20~23岁之内与之外
WHERE Sage BETWEEN 20 AND 23; --年龄在20~23之间
WHERE Sage NOT BETWEEN 20 AND 23; --年龄不在20~23之间
比如:查询数学系(MA)和信息系(IS)学生
WHERE Sdept IN ('MA', 'IS')
[NOT] LIKE '<匹配串>' [ESCAPE '<转码字符>']
其含义是查找指定的属性列值与 <匹配串> 相匹配的元组。<匹配串> 可以是一个完整的字符串,也可以含有通配符%和 _ 。 其中:
比如:查询以“DB_”开头,且倒数第二个字符为“设”的课程的详细情况。
WHERE Cname LIKE 'DB\_%设_' ESCAPE'\'; --“设”后面只有一个 _ (下横线);
注意:数据库字符集为ASCII时一个汉字需要两个_ ;当字符集为GBK时只需要一个_ 。
如果用户要查询的字符串本身就含有通配符 % 或 _ (下横线),这时就要使用 ESCAPE ‘<换码字符>’ 短语对通配符进行转义了。
相关例子 14~20 即 七、字符匹配
比如:查询计算机科学系年龄在21岁以下的学生姓名。
WHERE Sdept = 'CS' AND Sage < 21
比如:查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。
ORDER BY Sdept, Sage DESC; -- Sdept 升序; Sage 降序
COUNT(*) --统计元组个数
COUNT( [DISTINCT | ALL] <列名>) --统计一列中值的个数
SUM( [DISTINCT | ALL] <列名>) --计算一-列值的总和(此列必须是数值型)
AVG( [DISTINCT | ALL] <列名>) --计算一-列值的平均值(此列必须是数值型)
MAX( [DISTINCT | ALL] <列名>) --求一列值中的最大值
MIN( [DISTINCT | ALL] <列名>) --求一列值中的最小值
[<表名1>.] <列名1> <比较运算符> [<表名2>.] <列名2>
[<表名1>.] <列名1> BETWEEN [<表名2>.] <列名2> AND [<表名2>.] <列名3>
其中包括
子查询返回单值时可以用比较运算符,但返回多值时要用 ANY (有的系统用SOME) 或 ALL 谓词修饰符。而使用 ANY 或 ALL 谓词时则必须同时使用比较运算符。其语义如下所示:
> ANY 大于子查询结果中的某个值
> ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
>= ANY 大于等于子查询结果中的某个值
>= ALL 大于等于子查询结果中的所有值
<= ANY 小于等于子查询结果中的某个值
<= ALL 小于等于子查询结果中的所有值
= ANY 等于子查询结果中的某个值
= ALL 等于子查询结果中的所有值(通常没有实际意义)
!=(或<>) ANY 不等于子查询结果中的某个值
!=(或<>) ALL 不等于子查询结果中的任何一个值
ANY(或SOME)、ALL谓词与聚集函数、IN谓词的等价转换关系
= | <>或!= | < | <= | > | >= | |
---|---|---|---|---|---|---|
ANY | IN | – | <MAX | <=MAX | >MIN | >= MIN |
ALL | – | NOT IN | <MIN | <=MIN | >MAX | >=MAX |
SELECT …… --第一个查询
……
WHERE ……
UNION --可以换成 INTERSECT、EXCEPT
SELECT …… --第二个查询
……
WHERE ……
关系 Student:
Sno(学号) | Sname(姓名) | Ssex(性别) | Sage(年龄) | Sdept(所在系) |
---|---|---|---|---|
S01 | 刘一 | 男 | 21 | CS |
S02 | 陈二 | 女 | 18 | MA |
S03 | 张三 | 女 | 19 | MA |
S04 | 李四 | 男 | 21 | IS |
S05 | 王五 | 男 | 20 | CS |
S06 | 赵六 | 女 | 19 | IS |
关系 Course:
Cno(课程号) | Cname(课程名) | Pre_Cno(先修课程号) | Ccredit(学分) |
---|---|---|---|
C01 | 英语 | 4 | |
C02 | 数据结构 | C05 | 2 |
C03 | 数据库 | C02 | 2 |
C04 | DB_设计 | C03 | 3 |
C05 | C++ | 3 | |
C06 | 网络原理 | C07 | 3 |
C07 | 操作系统 | C05 | 3 |
关系 Report:
Sno(学号) | Cno(课程号) | Grade(考试成绩) |
---|---|---|
S01 | C01 | 92 |
S01 | C03 | 84 |
S02 | C01 | 71 |
S02 | C02 | 83 |
S02 | C05 | 88 |
S03 | C06 | 0 |
S04 | C03 | 94 |
S04 | C05 | 78 |
S05 | C03 | 84 |
S06 | C04 | NULL |
S06 | C06 | 89 |
不要吐槽为何都要考计算机相关知识,知识举个栗子而已,切勿当真。
SELECT Sno, Sname
FROM Student;
SELECT Sname, Sno, Sdept
FROM Student;
SELECT *
FROM Student;
等价于
SELECT Sno, Sname ,Ssex, Sage, Sdept
FROM Student;
SELECT Sname, 2020-Sage /* 查询结果的第2列是一个算术表达式*/
FROM Student;
SELECT Sname , 'Year of Birth: ', 2020-Sage , LOWER(Sdept)
FROM Student;
SELECT Sname NAME, 'Year of Birth:' BIRTH, 2020 - Sage BIRTHDAY, LOWER(Sdept) DEPARTMENT
FROM Student;
未去重版:
SELECT Sno
FROM Report;
等价于
SELECT ALL Sno
FROM Report;
去重版:
SELECT DISTINCT Sno
FROM Report;
←未去重版 去重版→
SELECT Sname
FROM Student
WHERE Sdept = 'CS';
SELECT Sname,Sage
FROM Student
WHERE Sage < 20;
SELECT DISTINCT Sno
FROM Report
WHERE Grade < 60;
谓词BETWEEN…AND…和 NOT BETWEEN…AND…可以用来查找属性值在( 或不在)指定范围内的元组,其中BETWEEN后是范围的下限(即低值),AND后是范围的上限(即高值),即 从…到… ,其范围是包括了低值和高值。
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage NOT BETWEEN 20 AND 23;
SELECT Sname,Ssex
FROM Student
WHERE Sdept IN ('MA', 'IS');
SELECT Sname, Ssex
FROM Student
WHERE Sdept NOT IN ('MA', 'IS');
谓词LIKE可以用来进行字符串的匹配。其一般语法格式如下:
[NOT] LIKE '<匹配串>' [ESCAPE '<换码字符>' ]
其含义是查找指定的属性列值与 <匹配串> 相匹配的元组。<匹配串> 可以是一个完整的字符串,也可以含有通配符%和 _ 。 其中:
SELECT *
FROM Student
WHERE Sno LIKE 'S02';
等价于
SELECT *
FROM Student
WHERE Sno = 'S02';
SELECT Sname, Sno, Ssex
FROM Student
WHERE Sname LIKE '刘%';
SELECT Sname
FROM Student
WHERE Sname LIKE '王_'; --只有一个_(下横线)
SELECT Sname, Sno
FROM Student
WHERE Sname LIKE '_五%'; --只有一个_(下横线)
SELECT Sname, Sno, Ssex
FROM Student
WHERE Sname NOT LIKE '刘%';
SELECT Cno, Ccredits
FROM Course
WHERE Cname LIKE 'DB\_设计' ESCAPE'\';
SELECT *
FROM Course
WHERE Cname LIKE 'DB\_%设_' ESCAPE'\'; --“设”后面只有一个 _ (下横线);
SELECT Sno, Cno
FROM Report
WHERE Grade IS NULL; --分数Grade是空值null
SELECT Sno, Cno
FROM Report
WHERE Grade IS NOT NULL;
SELECT Sname
FROM Student
WHERE Sdept = 'CS' AND Sage < 21;
在例12中的 IN 谓词实际上是多个OR运算符的缩写,因此该例中的查询也可以用OR运算符写成如下等价形式:
SELECT Sname, Ssex
FROM Student
WHERE Sdept = 'MA' OR Sdept = 'IS';
等价于:
SELECT Sname,Ssex
FROM Student
WHERE Sdept IN ('MA', 'IS');
SELECT Sno, Grade
FROM Report
WHERE Cno = 'C03'
ORDER BY Grade DESC;
SELECT *
FROM Student
ORDER BY Sdept, Sage DESC;
为了进一步方便用户,增强检索功能,SQL提供了许多聚集函数,主要有:
COUNT(*) --统计元组个数
COUNT( [DISTINCT | ALL] <列名>) --统计一列中值的个数
SUM( [DISTINCT | ALL] <列名>) --计算一-列值的总和(此列必须是数值型)
AVG( [DISTINCT | ALL] <列名>) --计算一-列值的平均值(此列必须是数值型)
MAX( [DISTINCT | ALL] <列名>) --求一列值中的最大值
MIN( [DISTINCT | ALL] <列名>) --求一列值中的最小值
SELECT COUNT(*)
FROM Student;
SELECT COUNT(DISTINCT Sno)
FROM Report;
SELECT AVG(Grade)
FROM Report
WHERE Cno = 'C01';
SELECT MAX(Grade)
FROM Report
WHERE Cno = 'C01';
SELECT SUM(Ccredit)
FROM Report, Course
WHERE Sno = 'S01' AND Report.Cno = Course.Cno;
SELECT Cno, COUNT(Sno)
FROM Report
GROUP BY Cno
SELECT Sno
FROM Report
GROUP BY Sno
HAVING COUNT(*) > 2;
SELECT Sno, AVG(Grade)
FROM Report
GROUP BY Sno
HAVING AVG(Grade) >= 85;
[<表名1>.] <列名1> <比较运算符> [<表名2>.] <列名2>
[<表名1>.] <列名1> BETWEEN [<表名2>.] <列名2> AND [<表名2>.] <列名3>
SELECT *
FROM Student, Report
WHERE Student.Sno = Report.Sno; /*将Student 与 Report中同一学生的元组连接起来*/
等价于:
SELECT Student.*, Report.*
FROM Student, Report
WHERE Student.Sno = Report.Sno;
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student, Report
WHERE Student.Sno = Report.Sno;
SELECT Student.Sno, Sname
FROM Student, Report
WHERE Student.Sno = Report.Sno --连接谓词
AND Report.Cno = 'C03' --其他限定条件
AND Report.Grade > 90;
SELECT FIRST.Cno, SECOND.Pre_Cno
FROM Course FIRST, Course SECOND
WHERE FIRST.Pre_Cno = SECOND.Cno;
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student LEFT OUTER JOIN Report ON (Student.Sno = Report.Sno);
数据不是很好,所有人都有选修课。。。NULL的效果看不出来
这里放一张课本上面的图吧,大致差不多,都是用NULL进行填充
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, Course, Report
WHERE Student.Sno = Report.Sno
AND Course.Cno = Report.Cno;
SELECT Sname
FROM Student
WHERE Sno IN
(SELECT Sno
FROM Report
WHERE Cno = 'C03');
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept IN (
SELECT Sdept
FROM Student
WHERE Sname = '刘一' --这后面不能直接加上 ; (分号)
);
SELECT Sno, Sname
FROM Student
WHERE Sno IN (
SELECT Sno
FROM Report
WHERE Cno IN (
SELECT Cno
FROM Course
WHERE Cname = '数据库'
)
);
SELECT Sno, Cno
FROM Report a
WHERE grade >= (
SELECT AVG(grade) /*某学生的平均成绩*/
FROM Report b
WHERE a.Sno = b.Sno);
① 从外层查询中取出 Report 的一个元组 a,将元组 a 的 Sno 值( S01 ) 传送给内层查询。
②执行内层查询,得到 S01 这个学生的选修平均成绩,用该值代替内层查询,得到外层查询。
③执行这个查询,得出结果。
求解相关子查询不能像求解不相关子查询那样一次将子查询求解出来,然后求解父查询。内层查询由于与外层查询有关,因此必须反复求值。
> ANY 大于子查询结果中的某个值
> ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
>= ANY 大于等于子查询结果中的某个值
>= ALL 大于等于子查询结果中的所有值
<= ANY 小于等于子查询结果中的某个值
<= ALL 小于等于子查询结果中的所有值
= ANY 等于子查询结果中的某个值
= ALL 等于子查询结果中的所有值(通常没有实际意义)
!=(或<>) ANY 不等于子查询结果中的某个值
!=(或<>) ALL 不等于子查询结果中的任何一个值
SELECT Sname, Sage
FROM Student
WHERE Sage < ANY(
SELECT Sage
FROM Student
WHERE Sdept = 'CS')
AND Sdept <> 'CS'; /*注意这是父查询块中的条件*/
SELECT Sname, Sage
FROM Student
WHERE Sage < ALL(
SELECT Sage
FROM Student
WHERE Sdept = 'CS')
AND Sdept <> 'CS'; /*注意这是父查询块中的条件*/
emmmmmm似乎和上一个例题的结果差不多。。。数据没设好,把计算机的学生的年龄设的都比较大了点。。。
SELECT Sname
FROM Student
WHERE EXISTS(
SELECT *
FROM Report
WHERE Sno = Student.Sno
AND Cno = 'C01');
SELECT Sname
FROM Student
WHERE NOT EXISTS(
SELECT *
FROM Report
WHERE Sno = Student.Sno
AND Cno = 'C01');
一些带 EXISTS 或 NOT EXISTS 谓词的子查询不能被其他形式的子查询等价替换,但所有带 IN 谓词、比较运算符、ANY 和 ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换。
SQL中没有全称量词 (forall),但是可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:
(∀x)P ≡ ¬(∃x(¬ P))
由于没有全称量词,但可将题目的意思转换成等价的用存在量词的形式。
SELECT *
FROM Student
WHERE Sdept = 'CS'
UNION
SELECT *
FROM Student
WHERE Sage <= 20;
SELECT *
FROM Student
WHERE Sdept = 'CS'
INTERSECT
SELECT *
FROM Student
WHERE Sage <= 20;
这实际上就是查询计算机科学系中年龄不大于19岁的学生。
SELECT *
FROM Student
WHERE Sdept = 'CS'
AND Sage <= 20;
SELECT *
FROM Student
WHERE Sdept = 'CS'
EXCEPT
SELECT *
FROM Student
WHERE Sage <= 20;
也就是查询计算机科学系中年龄大于20岁的学生。
SELECT *
FROM Student
WHERE Sdept = 'CS'
AND Sage > 20;
SELECT Sno, Cno
FROM Report, (SELECT Sno, AVG(Grade)
FROM Report
GROUP BY Sno
) AS Avg_report(avg_sno, avg_grade)
WHERE Report.Sno = Avg_report.avg_sno
AND Report.Grade >= Avg_report.avg_grade;
这里 FROM 子句中的子查询将生成一个派生表Avg_report。 该表由avg_sno 和 avg. grade 两个属性组成,记录了每个学生的学号及平均成绩。
主查询将 Report 表与 Avg.report 按学号相等进行连接,选出修课成绩大于其平均成绩的课程号。
需要说明的是,通过 FROM 子句生成派生表时,AS 关键字可以省略,但必须为派生关系指定一个别名。而对于基本表,别名是可选择项。
改文是基于课本例子进行适当的改写;
内容量有点大,个别地方可能有误,发现的话麻烦说一声;
把例子都敲一遍后都差不多能理解很多了——多练
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。