SQL多表连接总结

了解多表连接查询,就需要先了解多表连接查询的原理,通过实例加深认识。

多表查询原理:将多个表通过笛卡尔积形成一个虚表,再根据查询条件筛选符合条件的数据。

oracle复杂查询参考文档https://www.2cto.com/database/201805/747393.html

oracle复杂查询参考文档:https://www.cnblogs.com/mchina/archive/2012/09/09/2653417.html

1、Union

UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

UNION 运算符通过组合其他两个结果表(例如 TABLE1 和 TABLE2)并消去表中任何重复行而派生出一个结果表。

当 ALL 随 UNION 一起使用时(即 UNION ALL),不消除重复行。两种情况下,派生表的每一行不是来自 TABLE1 就是来自 TABLE2。

注意:union:用于将不同表中相同的列查询出的数据展示出来,不包括重复数据。(只能查询表中的相同列)

Union all :用于将不同表中相同的列查询出的数据展示出来,包括重复数据。(只能查询表中的相同列)

3)查询教师学生全部姓名

 因为UNION只会选择不同的值,如果学生中和教师中有重名的情况,这就需要

UNION ALL

SELECT Name FROM Students
UNION ALL
SELECT Name FROM Teachers

2、INNER JOIN(内连接)

INNER JOIN(内连接:inner可以省略),也称为自然连接

与select  a.* , b.*   from  表a, 表b where  a.id = b.id  等效,也是内连接(推荐使用join)

作用:根据两个或多个表中的列之间的关系,从这些表中查询数据。

注意: 内连接是从结果中删除其他被连接表中没有匹配行的所有行,所以内连接可能会丢失信息。

重点:内连接,利用笛卡尔积形成一张虚表,根据条件只保留匹配行。

语法:SELECT fieldlist   FROM table1 [INNER] join table2   ON table1.column=table2.column  

学生表信息(Students):

IDNameAgeCityMajorID
101Tom20Beijing10
102Lucy18Shanghai11

专业信息表(Majors): 

IDName
10English
12Computer

预置脚本:

DELETE FROM Students

INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(101,'Tom',20,'BeiJing',10)

INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(102,'Lucy',18,'ShangHai',11)

DELETE FROM Majors

INSERT INTO Majors(ID,Name) VALUES(10,'English')

INSERT INTO Majors(ID,Name) VALUES(12,'Computer')

实例:查询学生信息,包括ID,姓名、专业名称SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students INNER JOIN Majors
ON Students.MajorID = Majors.ID查询结果:

IDNameMajorName
101TomEnglish

根据结果可以清晰看到,确实只有匹配的行。学生Lucy的信息丢失了。

但是,inner join也会产生重复数据。如果将Majors表的主键约束去掉,可以插入重复的ID,如:DELETE FROM Majors
INSERT INTO Majors(ID,Name) VALUES(10,'English')
INSERT INTO Majors(ID,Name) VALUES(10,'Computer')

继续执行上面的关联语句,结果为:

IDNameMajorName
101TomEnglish
101TomComputer

如果是LEFT JOIN也会有重复记录,其结果为:

IDNameMajorName
101TomEnglish
101TomComputer
102LucyNull

RIGHT JOIN 结果与INNER JOIN一样。

后续我们会深入研究JOIN的具体原理。

3、外连接

与内连接相比,即使没有匹配行,也会返回一个表的全集。

外连接分为三种:左外连接,右外连接,全外连接。对应SQL:LEFT/RIGHT/FULL OUTER JOIN。通常我们省略outer 这个关键字。写成:LEFT/RIGHT/FULL JOIN。

重点:至少有一方保留全集,没有匹配行用NULL代替。

1)LEFT OUTER JOIN,简称LEFT JOIN,左外连接(左连接)

结果集保留左表的所有行,但只包含第二个表与第一表匹配的行。第二个表相应的空行被放入NULL值。

依然沿用内链接的例子

(1)使用左连接查询学生的信息,其中包括学生ID,学生姓名和专业名称。SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students LEFT JOIN Majors
ON Students.MajorID = Majors.ID

结果:

IDNameMajorName
101TomEnglish
102LucyNull

结论:

通过结果,我们可以看到左连接包含了第一张表的所有信息,在第二张表中如果没有匹配项,则用NULL代替。 

2)RIGHT JOIN(right outer join)右外连接(右连接)

右外连接保留了第二个表的所有行,但只包含第一个表与第二个表匹配的行。第一个表相应空行被入NULL值。

右连接与左连接思想类似。只是第二张保留全集,如果第一张表中没有匹配项,用NULL代替

依然沿用内链接的例子,只是改为右连接

(1)使用右连接查询学生的信息,其中包括学生ID,学生姓名和专业名称。SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students RIGHT JOIN Majors
ON Students.MajorID = Majors.ID

查询结果:

IDNameMajorName
101TomEnglish
NullNullComputer

通过结果可以看到,包含了第二张表Majors的全集,Computer在Students表中没有匹配项,就用NULL代替。 

3)FULL JOIN (FULL OUTER JOIN,全外连接)

全外连接,简称:全连接。会把两个表所有的行都显示在结果表中

1)使用全连接查询学生的信息,其中包括学生ID,学生姓名和专业名称。SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students FULL JOIN Majors
ON Students.MajorID = Majors.ID

查询结果: 

IDNameMajorName
101TomEnglish
102LucyNull
NullNullComputer

包含了两张表的所有记录,没有记录丢失,没有匹配的行用NULL代替。

4、CROSS JOIN(交叉连接)

交叉连接。交叉连接返回左表中的所有行,左表中的每一行与右表中的所有行组合。交叉连接也称作笛卡尔积。 

简单查询两张表组合,这是求笛卡儿积,效率最低。

笛卡儿积:笛卡尔乘积,也叫直积。假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。可以扩展到多个集合的情况。类似的例子有,如果A表示某学校学生的集合,B表示该学校所有课程的集合,则A与B的笛卡尔积表示所有可能的选课情况。

1)交叉连接查询学生的信息,其中包括学生ID,学生姓名和专业名称。SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students CROSS JOIN Majors

查询结果:

IDNameMajorName
101TomEnglish
102LucyEnglish
101TomComputer
102LucyComputer

2)查询多表,其实也是笛卡儿积,与CROSS JOIN等价,以下查询同上述结果一样。

这个可能很常见,但是大家一定要注意了,这样就查询了两张表中所有组合的全集。SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students,Majors

3)加了查询条件

注意:在使用CROSS JOIN关键字交叉连接表时,因为生成的是两个表的笛卡尔积,因而不能使用ON关键字,只能在WHERE子句中定义搜索条件。SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students CROSS JOIN Majors
WHERE Students.MajorID = Majors.ID

查询结果:

IDNameMajorName
101TomEnglish

查询结果与INNER JOIN一样,但是其效率就慢很多了。

5、全部实例脚本 

CREATE DATABASE TestDB
USE TestDB
------------------------------------------
--创建相关表
IF OBJECT_ID('Students','U') IS NOT NULL
DROP TABLE Students
--学生信息表
CREATE TABLE Students(
ID int primary key not null,
Name nvarchar(50),
Age int,
City nvarchar(50),
MajorID int
)
--专业信息表
IF OBJECT_ID('Majors','U') IS NOT NULL
DROP TABLE Majors

CREATE TABLE Majors(
ID int primary key not null,
Name nvarchar(50)
)
--教师信息表
IF OBJECT_ID('Teachers','U') IS NOT NULL
DROP TABLE Teachers
CREATE TABLE Teachers(
ID int primary key not null,
Name nvarchar(20) not null
)
--预置数据
DELETE FROM Students
INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(101,'Tom',20,'BeiJing',10)
INSERT INTO Students(ID,Name,Age,City,MajorID) VALUES(102,'Lucy',18,'ShangHai',11)

DELETE FROM Majors
INSERT INTO Majors(ID,Name) VALUES(10,'English')
INSERT INTO Majors(ID,Name) VALUES(12,'Computer')

DELETE FROM Teachers
INSERT INTO Teachers(ID,Name) VALUES(101,'Mrs Lee')
INSERT INTO Teachers(ID,Name) VALUES(102,'Lucy')

SELECT ID,Name FROM Students
UNION
SELECT ID,Name FROM Teachers

SELECT ID,Name FROM Students
UNION ALL
SELECT ID,Name FROM Teachers
--内连接
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students INNER JOIN Majors
ON Students.MajorID = Majors.ID
--左连接
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students LEFT JOIN Majors
ON Students.MajorID = Majors.ID
--右连接
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students LEFT JOIN Majors
ON Students.MajorID = Majors.ID
--全连接
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students FULL JOIN Majors
ON Students.MajorID = Majors.ID
--交叉连接
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students CROSS JOIN Majors
--交叉连接
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students CROSS JOIN Majors
WHERE Students.MajorID = Majors.ID
--一次查询多表
SELECT Students.ID,Students.Name,Majors.Name AS MajorName
FROM Students,Majors

                                                            知识分享不易,望您支持,只为更好!

知识分享不易,望您支持,只为更好
知识分享不易,望您支持,只为更好
  • 17
    点赞
  • 103
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一位远方的诗人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值