SQL 连接查询

本文最后更新于:2024年3月18日 凌晨

SQL 连接查询

JOIN

img

INNER JOIN

  • INNER JOIN 关键字在表中存在至少一个匹配时返回行。

1
2
3
4
5
6
7
8
9
SELECT column_name(s)
FROM table1
INNER JOIN table2
ON table1.column_name=table2.column_name;
-- 或。
SELECT column_name(s)
FROM table1
JOIN table2
ON table1.column_name=table2.column_name;
  • 注意:INNER JOIN 与 JOIN 是相同的。

LEFT JOIN

  • LEFT JOIN 关键字从左表(table1)返回所有的行,即使右表(table2)中没有匹配,如果右表中没有匹配,则结果为 NULL

1
2
3
4
5
6
7
8
9
10
SQL LEFT JOIN 语法。
SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name=table2.column_name;
-- 或。
SELECT column_name(s)
FROM table1
LEFT OUTER JOIN table2
ON table1.column_name=table2.column_name;
  • 注意:在某些数据库中,LEFT JOIN 称为 LEFT OUTER JOIN

RIGHT JOIN

  • RIGHT JOIN 关键字从右表(table2)返回所有的行,即使左表(table1)中没有匹配,如果左表中没有匹配,则结果为 NULL

1
2
3
4
5
6
7
8
9
SELECT column_name(s)
FROM table1
RIGHT JOIN table2
ON table1.column_name=table2.column_name;
-- 或。
SELECT column_name(s)
FROM table1
RIGHT OUTER JOIN table2
ON table1.column_name=table2.column_name;
  • 注意:在某些数据库中,RIGHT JOIN 称为 RIGHT OUTER JOIN

FULL JOIN

  • FULL OUTER JOIN 关键字只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行。
  • FULL OUTER JOIN 关键字结合了 LEFT JOIN 和 RIGHT JOIN 的结果。

SQL FULL OUTER JOIN 语法

1
2
3
4
SELECT column_name(s)
FROM table1
FULL OUTER JOIN table2
ON table1.column_name=table2.column_name;

等值与非等值连接查询

  • 连接查询的WHERE子句中用来连接两个表的条件称为连接条件或连接谓词,其一般格式为。
1
[<表名1>.] <列名1> <比较运算符> [<表名2>.] <列名2>
  • 其中比较运算符主要有=,>,<,>=,<=,!=(或<>) 等。
  • 外连接谓词还可以使用下面形式:
1
[<  >.] <列名1> BETWEEN [<表名2>.] <列名2> AND [<表名3>.] <列名3>
  • 当连接运算符为=时,称为等值连接,使用其他运算符称为非等值连接。
  • 连接谓词中的列名称为连接字符,连接条件中的各连接字段类型必须是可比的,但名字不必相同。

[例3.49]:查询每个学生及其选修课程的情况。

  • 学生情况存放在Student表中,学生选课情况存放在SC表中,所以本查询实际上涉及Student与SC两个表,这两个表之间的联系是通过公共属性Sno实现的。
1
2
3
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno;/*将Student与SC中同一学生的元组连接起来*/
  • 结果为。
Student.Sno Sname Ssex Sage Sdept SC.Sno Cno Grade
201215121 李勇 20 CS 201215121 1 92
201215121 李勇 20 CS 201215121 2 85
201215121 李勇 20 CS 201215121 3 88
201215122 刘晨 19 CS 201215122 2 90
201215122 刘晨 19 CS 201215122 3 80
  • 本例中,SELECT子句与WHERE子句中的属性名前都加上了表名前缀,这是为了避免混淆,如果属性名在参加连接的各表中是唯一的,则可以省略表名前缀。
  • 关系数据库管理系统执行该连接操作的一种可能过程是:首先在表Student中找到第一个元组,然后从头开始扫描SC表,逐一查找于Student第一个元组的Sno相等的SC元组,找到后就将Student中的第一个元组于该元组拼接起来,形成结果表中一个元组,SC全部查找完成后,再找Student中的第二个元组,然后再从头开始扫描SC,逐一查找满足连接条件的元组,找到后就将Student中的第二个元组与该元组拼接起来,形成结果表中一个元组,重复上述的操作,知道Student中的全部元组都处理完毕为止,这就是嵌套循环连接算法的基本思想。
  • 如果在SC表Sno上建立了索引的话,就不用每次全表扫描SC表了,而是根据Sno值通过索引找到相应的SC元组,用索引查询SC中满足条件的元组一般会比全表扫描块。
  • 若在等值连接中把目标中重复的属性列去掉则为自然连接。

[例3.50]:对例3.49用自然连接完成。

1
2
3
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno=SC.Sno;
  • 本例中,由于Student.Sno,Sname,Ssex,Sage,Sdept,Cno和Grade属性列在Student表与SC表中是唯一的,因此引用时可以去掉表名前缀,而Sno在两个表都出现了,因此引用时必须加上表名前缀。
  • 一条SQL语句可以同时完成选择和连接查询,这时WHERE子句是由连接谓词和选择谓词组成的复合条件。

[例3.51]:查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。

1
2
3
4
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND /*连接谓词*/
SC.Cno='2' AND SC.Grade>90;/*其他限定条件*/
  • 该查询的一种优化(高效)的执行过程是,先从SC中挑选出Cno='2’并且Grade>90的元组形成一个中间关系,再和Student中满足连接条件的元组进行连接得到最终的结果关系。

自身连接

  • 连接操作不仅可以在两个表之间进行,也可以是一个表与其自己进行连接,称为表的自身连接。

[例3.52]:查询每一门课的间接先修课(即先修课的先修课)

  • 在Course表中只有每门课的之间先修课信息,而没有先修课的先修课,要得到这个信息,必须先对一门课找到其先修课,再按此先修课的课程号查找它的先修课程,这就要将Cours表与其自身连接。
  • 为此,要为Course表取两个别名,一个是FIRST,另一个是SECOUND

FIRST表(Course表)

Cno Cname Cpno Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 数据处理 2
7 PASCAL语言 6 4

SECOUND表(Course表)

Cno Cname Cpno Ccredit
1 数据库 5 4
2 数学 2
3 信息系统 1 4
4 操作系统 6 3
5 数据结构 7 4
6 数据处理 2
7 PASCAL语言 6 4
  • 完成该查询的SQL语句为:
1
2
3
SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno=SECOND.Cno;
  • 结果为。
Cno Cpno
1 7
3 5
5 6

多表连接

  • 连接操作除了可以是两表连接,一个表与其自身连接外,还可以是两个以上的表进行连接,后者通常称为多表连接关系。

[例3.54]:查询每个学生的学号,姓名,选修的课程名及成绩。

1
2
3
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
  • 关系数据库管理系统在执行多表连接时,通常是先进行两个表的连接操作,再将其连接结果与第三个表进行连接,本例中的一种可能的执行方式是,先将Student表与SC表进行连接,得到每个学生的学号,姓名,所选课程号和相对应的成绩,然后再将其与Course表进行连接,得到最终结果。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!