MS SQL Server 中各种 JOIN 的区别






4.96/5 (13投票s)
在这里,我们将了解 MS SQL Server 中各种连接的基本区别或相似之处。
引言
在使用 SQL 连接时,我们可以根据需求从各种选择中进行选择。 好的,每个连接序列可能彼此不同,并服务于特定目的。 但其中一些连接查询在语法/性能上有所不同,但它们产生的结果相同。 为了避免混淆,我们将在这里了解 MS SQL Server 中各种连接的基本区别和相似之处。
背景
假设我们有两个表
CREATE Table Student
(
Id BIGINT,
Name VARCHAR(100)
);
CREATE Table StudentAge
(
Student_Id BIGINT, --foreign key from Student tables Id column
Name VARCHAR(100),
Age INT
);
是的,它们之间没有实际的外键,但假设我们用关系数据填充这些表,如下所示
INSERT INTO Student
VALUES
(1, 'Dipon'),
(2, 'Dip'),
(3, 'Dipa'), -- no age
(4, 'Dipika'), -- no age
(5, 'Shamim'), -- has age more than once
(6, 'Shatu'), -- same person twice
(6, 'Shatu')
INSERT INTO StudentAge
VALUES
(1, 'Dipon', 10),
(2, 'Dip', 20),
(5, 'Shamim', 40), -- same person twice age
(5, 'Shamim', 50),
(6, 'Shatu', 50), -- same age to more than one people
(7, 'Jamal', 50), -- no Student
(8, 'Kamal', 60) -- no Student
如我们所见,考虑到这两个表,有些行具有关系数据,而有些则没有。
开始连接
绅士们喜欢握手
有时,他们只在彼此认识时握手。
有时,即使他们彼此不认识,他们也会这样做。
有时,如果找不到人握手,一个人可能会感到尴尬。
握手 - 行之间的连接
彼此认识 - 具有任何数据关系
尴尬显现 - 没有找到要连接的行,NULL
常规连接
如果他们认识彼此就握手,没有尴尬显现。
连接:JOIN
/*Join: JOIN*/
/*does: Shakes hand if they know each other, no embarrassment revealed*/
SELECT *
FROM Student
JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
连接:INNER JOIN
/*Join: INNER JOIN*/
/*does: as JOIN*/
SELECT *
FROM Student
INNER JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
连接:WHERE
/*Join: WHERE*/
/*does: as JOIN*/
SELECT *
FROM Student, StudentAge
WHERE Student.Id = StudentAge.Student_Id;
CROSS APPLY
/*CROSS APPLY*/
/*does: as JOIN*/
SELECT *
FROM Student
CROSS APPLY(
SELECT *
FROM StudentAge
WHERE Student.Id = StudentAge.Student_Id
)StudentAges
它们都产生相同的结果
http://www.sqlfiddle.com/#!3/517ad/1
左连接
每个人如果认识彼此就握手,左边的人会感到尴尬。
连接:LEFT JOIN
/*Join: LEFT JOIN*/
/*does: Each person shakes hand if they know each other, embarrassment revealed for the left man*/
SELECT *
FROM Student
LEFT JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
连接:LEFT OUTER JOIN
/*Join: LEFT OUTER JOIN*/
/*does: as LEFT JOIN*/
SELECT *
FROM Student
LEFT OUTER JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
OUTER APPLY
/*OUTER APPLY*/
/*does: as LEFT JOIN*/
SELECT *
FROM Student
OUTER APPLY(
SELECT *
FROM StudentAge
WHERE Student.Id = StudentAge.Student_Id
)StudentAges
它们都产生相同的结果。
http://www.sqlfiddle.com/#!3/517ad/2
右连接
每个人如果认识彼此就握手,右边的人会感到尴尬。
连接:RIGHT JOIN
/*Join: RIGHT JOIN*/
/*does: Each person shakes hand if they know each other, embarrassment revealed for the right man*/
SELECT *
FROM Student
RIGHT JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
连接:RIGHT OUTER JOIN
/*Join: RIGHT OUTER JOIN*/
/*does: as RIGHT JOIN*/
SELECT *
FROM Student
RIGHT OUTER JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
OUTER APPLY
/*OUTER APPLY*/
/*does: as LEFT JOIN, but presented as RIGHT JOIN using (SELECT Students.*, StudentAge.**/
SELECT Students.*, StudentAge.*
FROM StudentAge
OUTER APPLY(
SELECT *
FROM Student
WHERE StudentAge.Student_Id = Student.Id
)Students
它们都产生相同的结果。
http://www.sqlfiddle.com/#!3/517ad/3
全连接
每个人如果认识彼此就握手,双方都会感到尴尬。
连接:FULL JOIN
/*Join: FULL JOIN*/
/*does: Each person shakes hand if they know each other, embarrassment revealed for the both man*/
SELECT *
FROM Student
FULL JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
连接:FULL OUTER JOIN
/*Join: FULL OUTER JOIN*/
/*does: as FULL JOIN*/
SELECT *
FROM Student
FULL OUTER JOIN StudentAge ON Student.Id = StudentAge.Student_Id;
它们都产生相同的结果。
http://www.sqlfiddle.com/#!3/517ad/4
交叉连接
每个人都与每个人握手。
连接:CROSS JOIN
/*Join: CROSS JOIN*/
/*does: Each one shakes hand with every one*/
SELECT *
FROM Student
CROSS JOIN StudentAge;
连接:TABLE
/*Join: TABLE*/
/*does: as CROSS JOIN*/
SELECT *
FROM Student, StudentAge;
CROSS APPLY
/*CROSS APPLY*/
/*does: as CROSS JOIN*/
SELECT *
FROM Student
CROSS APPLY(
SELECT *
FROM StudentAge
)StudentAges
它们都产生相同的结果。
http://www.sqlfiddle.com/#!3/517ad/5
其他连接!!!
在使用连接时,我们可能会遇到想要做更多事情的情况,例如
- 排除 INNER JOIN 的 LEFT JOIN
- 排除 INNER JOIN 的 RIGHT JOIN
- 排除 INNER JOIN 的 OUTER JOIN
- 等等,或者一些基本知识
请查看 https://codeproject.org.cn/Articles/33052/Visual-Representation-of-SQL-Joins,这是一篇由 C.L. Moffatt 撰写的精彩文章。
交叉/外部应用!!!
使用交叉/外部应用的目的仅仅是性能问题。 它比正常的连接执行得更快。 更多信息,请参阅
- http://www.mssqltips.com/sqlservertip/1958/sql-server-cross-apply-and-outer-apply/
- http://technet.microsoft.com/en-us/library/ms175156%28v=sql.105%29.aspx
限制
是的,我可能误解或呈现了一些内容。 如果您发现任何问题,请告诉我。