我在SQL Server中浏览了一篇关于CROSS APPLY
和OUTER APPLY
的文章。以下表格用于说明两者。
员工表:
EmployeeID FirstName LastName DepartmentID
1 Orlando Gee 1
2 Keith Harris 2
3 Donna Carreras 3
4 Janet Gates 3
部门表:
DepartmentID Name
1 Engineering
2 Administration
3 Sales
4 Marketing
5 Finance
我理解OUTER APPLY
与LEFT OUTER JOIN.
类似但是当我在表格之间应用OUTER APPLY
时,
select * from Department e
outer apply
Employee d
where d.DepartmentID = e.DepartmentID
我得到了以下结果(与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
当我在表之间应用OUTER APPLY
时,如下所示(right table
作为子查询)。
select * from Department e
outer apply
(
select * from
Employee d
where d.DepartmentID = e.DepartmentID
)a
我得到了以下结果(与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
有人可以解释为什么这两个查询给出了不同的outputs
?
答案 0 :(得分:7)
我认为理解这一点的关键是查看此查询的输出:
<option th:each="item:${list}" value="${item}"> some product $ </option>
这只是给你两张桌子的笛卡尔积:
select * from Department e
outer apply
Employee d
--where d.DepartmentID = e.DepartmentID
现在当您在where子句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
中添加回来时,您将消除大部分行:
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
这与以下内容相同:
SELECT * FROM Department e
CROSS JOIN Employee d
WHERE d.DepartmentID = e.DepartmentID;
所以即使你有一个SELECT * FROM Department e
INNER JOIN Employee d
ON d.DepartmentID = e.DepartmentID;
你的where子句把它变成OUTER APPLY
,从而删除没有雇员的部门。
答案 1 :(得分:2)
您可以在部门和员工之间看到下面的第一个查询外部申请计划。由于您的where
子句,它将转换为内连接。
第二个查询的执行计划,显示Department和employee表之间的Left outer join。在每个部门的第二个查询中,如果没有员工在场子查询,则检查员工将返回null。
但是在第一个查询中,由于NULL
子句而导致where
值的行被删除。
在图像&#39; e&#39;并且&#39; d&#39;是employee
和department
表。
答案 2 :(得分:1)
虽然您可以使用apply operator加入表格,但这不是它的设计目的。主要目的来自MSDN:
APPLY运算符允许您为其调用表值函数 查询的外表表达式返回的每一行。
顾名思义;表值函数是返回表的任何函数。这是一个简单的功能:
-- Function that takes a number, adds one and returns the result.
CREATE FUNCTION AddOne
(
@StartNumber INT
)
RETURNS TABLE
AS
RETURN
(
SELECT
@StartNumber + 1 AS [Result]
)
GO
这里有一些示例数据:
-- Sample data.
DECLARE @SampleTable TABLE
(
Number INT
)
;
INSERT INTO @SampleTable
(
Number
)
VALUES
(1),
(2),
(3)
;
将函数应用于我们的表,如下所示:
-- Using apply.
SELECT
st.Number,
ad.Result
FROM
@SampleTable AS st
CROSS APPLY AddOne(st.Number) AS ad
;
返回:
Number Result
1 2
2 3
3 4
Robert Sheldon的博客文章更详细地解释了上述内容。
apply运算符也可以与table value constructor结合使用,以通过其他方法返回完全相同的结果:
-- Using TVC.
SELECT
st.Number,
ad.Result
FROM
@SampleTable AS st
CROSS APPLY
(
VALUES
(st.Number + 1)
) AS ad(Result)
;
这种强大的技术允许您对数据执行计算,并为结果提供别名。
对于apply运算符,这个答案几乎没有触及表面。它还有很多技巧。我强烈建议进一步研究。