65.9K
CodeProject 正在变化。 阅读更多。
Home

MS SQL Server 中各种 JOIN 的区别

2014 年 8 月 18 日

CPOL

2分钟阅读

viewsIcon

27260

downloadIcon

163

在这里,我们将了解 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 撰写的精彩文章。

交叉/外部应用!!!

使用交叉/外部应用的目的仅仅是性能问题。 它比正常的连接执行得更快。 更多信息,请参阅

限制

是的,我可能误解或呈现了一些内容。 如果您发现任何问题,请告诉我。

© . All rights reserved.