三、多表连接查询
当查询的数据来自多个表时,需使用连接查询,核心是通过关联字段将多个表关联起来,常用连接方式:等值连接、自连接、外连接、多表连接。
1. 等值与非等值连接
等值连接是最常用的连接方式,通过**=**判断关联字段的值是否相等,实现多表关联;非等值连接使用>、<、BETWEEN等运算符,适用于非相等条件的关联。
— 等值连接:查询每个学生及其选修课程的情况(关联Student和SC表,学号为关联字段)
SELECT Student.*, SC.* FROM Student, SC WHERE Student.Sno = SC.Sno;
— 简化写法:指定需要查询的字段,关联字段加表名前缀
SELECT Student.Sno, Sname, Cno, Grade FROM Student, SC WHERE Student.Sno = SC.Sno;
— 等值连接加条件:查询选修2号课程且成绩90分以上的学生学号和姓名
SELECT Student.Sno, Sname FROM Student, SC WHERE Student.Sno=SC.Sno AND SC.Cno='2' AND SC.Grade>90;
2. 自连接
自连接是将一张表与自身进行连接,需为表指定不同的别名,将一张表当作多张表使用,适用于查询表内的关联关系。
— 查询每一门课的间接先修课(关联Course表自身,先修课号与课程号为关联字段)
SELECT FIRST.Cno, SECOND.Cpno FROM Course FIRST, Course SECOND WHERE FIRST.Cpno = SECOND.Cno;
3. 外连接
内连接仅返回两张表中关联字段匹配的记录,外连接会返回一张表的所有记录,另一张表中无匹配记录时,对应字段为NULL;常用外连接:左外连接(LEFT JOIN)、右外连接(RIGHT JOIN)。
左外连接返回左表的所有记录,右表无匹配则补NULL;右外连接反之;语法为:表1 JOIN 表2 ON 关联条件。
— 左外连接:查询所有学生的学号、姓名及选修课程情况(包括未选课的学生)
SELECT Student.Sno, Sname, Cno, Grade FROM Student LEFT JOIN SC ON Student.Sno = SC.Sno;
— 右外连接:查询所有课程的选修情况(包括无学生选修的课程)
SELECT SC.*, Cname FROM SC RIGHT JOIN Course ON SC.Cno = Course.Cno;
4. 多表连接
当查询数据来自3张及以上表时,使用多表连接,可连续使用JOIN关键字,也可使用逗号分隔表名加关联条件,核心是依次指定表之间的关联字段。
— 多表连接:查询每个学生的学号、姓名、选修课程名及成绩(关联Student、SC、Course三张表)
SELECT Student.Sno, Sname, Cname, Grade FROM Student, SC, Course WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
— 左外连接实现多表连接:包括未选课的学生
SELECT S.Sno, Sname, Cname, Grade FROM Student S LEFT JOIN SC ON S.Sno=SC.Sno LEFT JOIN Course C ON SC.Cno=C.Cno;
四、嵌套查询(子查询)
嵌套查询是将一个查询语句(子查询)嵌套在另一个查询语句(主查询)中,子查询的结果作为主查询的条件或数据源;子查询需用括号()包裹,子查询中不能使用ORDER BY子句,ORDER BY仅对最终结果排序。
1. 带有IN谓词的子查询
子查询的结果为一个集合,主查询使用IN判断字段值是否属于该集合,是最常用的嵌套查询方式。
— 查询与“刘晨”在同一个系学习的学生姓名(先查刘晨的系别,再查该系的所有学生)
SELECT Sname FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname='刘晨');
— 多层嵌套:查询选修了课程名为“数据结构”的学生学号和姓名
SELECT Sno, Sname FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Cno IN (SELECT Cno FROM Course WHERE Cname='数据结构'));
嵌套查询核心补充知识点
1. 子查询按执行时机分为:相关子查询(主查询执行一次,子查询执行多次)、非相关子查询(子查询先执行,结果供主查询使用);
2. 带有IN的子查询均为非相关子查询,执行效率较高;
3. 子查询可用于WHERE、FROM、SELECT子句后:WHERE后作为条件,FROM后作为临时表,SELECT后作为查询列;
4. 可用EXISTS替代IN,实现存在性判断,EXISTS子查询只需判断是否有结果返回,无需返回具体数据,大数据量下效率更高。





