OUTER在没有子查询的情况下应用

bms*_*dev 4 t-sql sql-server join sql-server-2012 outer-apply

我通过文章去约CROSS APPLY,并OUTER APPLY在SQL Server中.以下表格用于说明两者.

员工表:

EmployeeID  FirstName   LastName    DepartmentID

1           Orlando     Gee         1
2           Keith       Harris      2
3           Donna       Carreras    3
4           Janet       Gates       3
Run Code Online (Sandbox Code Playgroud)

部门表:

DepartmentID    Name
1               Engineering
2               Administration
3               Sales
4               Marketing
5               Finance
Run Code Online (Sandbox Code Playgroud)

我明白这OUTER APPLY是类似于LEFT OUTER JOIN.但当我OUTER APPLY在表之间应用如下,

select * from Department e
outer apply
Employee d
where d.DepartmentID = e.DepartmentID
Run Code Online (Sandbox Code Playgroud)

我得到了以下结果(与INNER JOIN结果相同)

DepartmentID    Name           EmployeeID   FirstName   LastName    DepartmentID
1               Engineering     1           Orlando     Gee          1
2               Administration  2           Keith       Harris       2
3               Sales           3           Donna       Carreras     3
3               Sales           4           Janet       Gates        3
Run Code Online (Sandbox Code Playgroud)

当我OUTER APPLY 在表之间应用如下(right table作为子查询).

select * from Department e
outer apply
(
select * from
Employee d
where d.DepartmentID = e.DepartmentID
)a
Run Code Online (Sandbox Code Playgroud)

我得到了以下结果(与LEFT OUTER JOIN结果相同)

DepartmentID    Name           EmployeeID   FirstName   LastName    DepartmentID
1               Engineering     1           Orlando     Gee          1
2               Administration  2           Keith       Harris       2
3               Sales           3           Donna       Carreras     3
3               Sales           4           Janet       Gates        3
4               Marketing       NULL        NULL        NULL         NULL
5               Finance         NULL        NULL        NULL         NULL
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么这两个查询有所不同outputs吗?

Gar*_*thD 7

我认为理解这一点的关键是看到这个查询的输出:

select * from Department e
outer apply
Employee d
--where d.DepartmentID = e.DepartmentID
Run Code Online (Sandbox Code Playgroud)

这只是简单地给你两个表的笛卡尔积:

DepartmentID    Name            EmployeeID  FirstName   LastName    DepartmentID
--------------------------------------------------------------------------------------
1               Engineering     1           Orlando     Gee         1
2               Administration  1           Orlando     Gee         1
3               Sales           1           Orlando     Gee         1
4               Marketing       1           Orlando     Gee         1
5               Finance         1           Orlando     Gee         1
1               Engineering     2           Keith       Harris      2
2               Administration  2           Keith       Harris      2
3               Sales           2           Keith       Harris      2
4               Marketing       2           Keith       Harris      2
5               Finance         2           Keith       Harris      2
1               Engineering     3           Donna       Carreras    3
2               Administration  3           Donna       Carreras    3
3               Sales           3           Donna       Carreras    3
4               Marketing       3           Donna       Carreras    3
5               Finance         3           Donna       Carreras    3
1               Engineering     4          Janet        Gates       3   
2               Administration  4          Janet        Gates       3   
3               Sales           4          Janet        Gates       3   
4               Marketing       4          Janet        Gates       3   
5               Finance         4          Janet        Gates       3   
Run Code Online (Sandbox Code Playgroud)

现在,当您在where子句中添加回来时,您将where d.DepartmentID = e.DepartmentID消除大部分这些行:

DepartmentID    Name            EmployeeID  FirstName   LastName    DepartmentID
--------------------------------------------------------------------------------------
1               Engineering     1           Orlando     Gee         1
2               Administration  2           Keith       Harris      2
3               Sales           3           Donna       Carreras    3
3               Sales           4          Janet        Gates       3   
Run Code Online (Sandbox Code Playgroud)

此查询在语义上等效于:

SELECT * FROM Department e
CROSS JOIN Employee d
WHERE d.DepartmentID = e.DepartmentID;
Run Code Online (Sandbox Code Playgroud)

这与以下内容相同:

SELECT * FROM Department e
INNER JOIN Employee d
ON d.DepartmentID = e.DepartmentID;
Run Code Online (Sandbox Code Playgroud)

因此,即使你有一个OUTER APPLYwhere子句将其转换成一个INNER JOIN,从而删除没有员工的部门.