学习了连接查询和嵌套查询。
今天启动SQL server,显示无法连接到服务器,重新打开软件还是一样,后来通过搜索重新启动了SQL server的服务,就可以了。 此电脑右键-管理-展开服务与应用程序,点击服务,右侧找到SQL server(MSSQLSERVER),
【3.49】查询每个学生及其选修课程的情况
SELECT Student.*, SC.*
FROM Student, SC
WHERE Student.Sno = SC.Sno;
等值连接查询,连接运算符是 = ,所以查询的条件是等号两边的值相等
在这里,SELECT Student.*,SC. * 可以等价为 SELECT *
思考:如何用SQL表达笛卡尔积 X?
运行以下语句:
SELECT Student.Sno,Sname
FROM Student, SC
得到以下结果,可以看到有50条记录。
再打开SC和Student表,能够看到,他们分别有5个元组和10个元组,所以在查询SELECT,FROM之后,就已经相当于列出了两个表的笛卡尔积,行数是乘积,列数是相加。不写查询语句的条件就是笛卡尔积。
【3.50】对3.49用自然连接完成。
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno;
自然连接就是在所有的列中去掉相同的列,像例子 中Student和SC中的Sno是相同的,保留一列即可。
【3.51】查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
SELECT Student.Sno, Sname
FROM Student, SC
WHERE Student.Sno=SC.Sno
AND SC.Cno='2'
AND SC.Grade>89;
一条SQL语句可以同时完成选择和连接查询。 AND是 连接 的意思。先从SC中选择出Cno='2’并且Grade>89的元组形成一个中间关系,再和Student中满足连接条件的元组进行连接得到最终的结果关系。
【3.52】查询每一门课的间接先修课(即先修课的先修课)
SELECT FIRST.Cno, SECOND.Cpno
FROM Course FIRST, Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
这里用的是自身连接,即自已与自己连接。因为用的是同一个表,所以使用时要给他们起别名。FROM后面的Course FIRST表示将表Course起别名为FIRST。
【3.53】
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student LEFT OUTER JOIN SC ON (Student.Sno=SC.Sno);
这里用了外连接,它不仅可以输出满足查询条件的元组,也可以输出不满足条件的元组。 左外连接是列出左边关系中所有的元组 ,右外连接是列出右边关系中所有的元组 。
例子中 LEFT OUTER JOIN为左外连接,除了满足的条件,Student的元组也被列出。如图,前五项为满足查询条件的元组,后八项为Student表中剩余的元组:
右连接:右表中的元组全部满足输出条件
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student RIGHT OUTER JOIN SC ON (Student.Sno=SC.Sno);
外连接:
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student FULL OUTER JOIN SC ON (Student.Sno=SC.Sno);
【3.54】
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, SC, Course
WHERE Student.Sno = SC.Sno
AND SC.Cno = Course.Cno;
多表连接:两个以上的表进行连接。可以对多张表进行操作。
【3.55】查询与“刘晨”在同一个系学习的学生。
--第一种方法:
--确定“刘晨”所在系名
SELECT Sdept
FROM Student
WHERE Sname= '刘晨';
--结果为: CS
--查找所有在CS系学习的学生。
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept= 'CS';
先查询刘晨所在的系,将查询的结果应用在第二段语句中,可以得出结果
执行结果:
--第二种方法,将第一步查询嵌入到第二部查询的条件中
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname= '刘晨');
在一个两层的嵌套查询中,括号外面为外层查询或父查询,括号里为内层查询或者子查询。(不能使用ORDER BY子句)
不相关子查询指的是子查询的查询条件不依赖于父查询,子查询语句先处理,处理完再处理父查询,由里向外查询。
相关子查询则不同,子查询的查询条件依赖于父查询,取父查询的一个元组,看它与子查询语句是否相符,相符就放在结果表,再取下一个元组重复操作,直至所有元组检查完。
第二种方法是带有IN谓词的子查询,运用不相关子查询。
执行结果与上方法一致。
--第三种方法:用自身连接完成查询要求
SELECT S1.Sno, S1.Sname,S1.Sdept
FROM Student S1,Student S2
WHERE S1.Sdept = S2.Sdept AND
S2.Sname = '刘晨';
第三种方法是用自身连接完成查询的,执行结果与上面两种方法一致。
它不如上面两种方法逻辑清晰。它的查询条件是表一的系和表二的相同,并且表二中元组的Sname为 ‘李晨’,查询结果应为表一中的Sno,Sname,Sdept,而且这些属性满足Stept应该是表二中 ‘李晨’的系。所以就是查询与李晨相同系别的学生。
【3.56】查询选修了课程名为“信息系统”的学生学号和姓名
SELECT Sno,Sname
FROM Student
WHERE Sno IN
(SELECT Sno
FROM SC
WHERE Cno IN
(SELECT Cno
FROM Course
WHERE Cname= '信息系统'
)
);
不相关子查询。先查询‘信息系统’的课程号,再查询这个课程号再课程表里的学号(选修了这门课的学生学号),再查询这些学生学号的姓名和学号。
等价于:
SELECT Student.Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno = SC.Sno AND
SC.Cno = Course.Cno AND
Course.Cname='信息系统';
三层嵌套之间没有关系,所以是不相关子查询。
【3.57】找出每个学生超过他选修课程平均成绩的课程号。
SELECT Sno, Cno
FROM SC x
WHERE Grade >=( SELECT AVG(Grade)
FROM SC y
WHERE y.Sno=x.Sno);
这是带有比较运算符的子查询,而且是相关子查询。
带比较符号运算: 当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或< >)。
从外层查询中取出SC的一个元组x,将x的Sno值传递给内层查询。
这里是选取课程表中的一个元组,查询这个元组学生成绩的平均值(内部嵌套完成),然后再看他的成绩是否大于这个平均值,是就放入结果表,进行下一个元组。
【3.58】查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
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 <
(SELECT MAX(Sage)
FROM Student
WHERE Sdept= 'CS ')
AND Sdept <> 'CS';
带有ANY(SOME)或ALL谓词的子查询。
使用ANY或ALL谓词时必须同时使用比较运算语义为:
> ANY 大于子查询结果中的某个值
> ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
>= ANY 大于等于子查询结果中的某个值
>= ALL 大于等于子查询结果中的所有值
!=(<>) ANY 不等于查询结果中的某个值
!=(<>) ALL 不等于查询结果中的任何一个值
【3.59】查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。
--第一种方法
SELECT Sname,Sage
FROM Student
WHERE Sage < ALL
(SELECT Sage
FROM Student
WHERE Sdept= 'CS')
AND Sdept <> 'CS';
不相关子查询,子查询查询出所有计算机科学系的学生的年龄,然后查询比这个年龄小并且不属于计算机科学系的学生姓名及年龄。
--第二种方法
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MIN(Sage)
FROM Student
WHERE Sdept= 'CS')
AND Sdept <>'CS';
子查询查询出计算机科学系学生年龄最小值,然后查询比这个最小值小的且不属于计算机科学系的学生的姓名及年龄。和上面其实是一样的。
ANY(或SOME),ALL谓词与聚集函数、IN谓词的等价转换关系: