2016-11-17 49 views
4

我在SQL Server中閱讀了有關CROSS APPLYOUTER APPLY的文章。以下表格用於說明兩者。OUTER適用於子查詢

Employee表:

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 

我得到低於結果(S AME如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

回答

7

我認爲關鍵要理解,這是看到了這個查詢的輸出:

select * from Department e 
outer apply 
Employee d 
--where d.DepartmentID = e.DepartmentID 

它只是給你兩個表的笛卡爾乘積:

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子句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; 

這是equabalent到:

SELECT * FROM Department e 
INNER JOIN Employee d 
ON d.DepartmentID = e.DepartmentID; 

所以,即使你有一個OUTER APPLY您的where子句把它變成一個INNER JOIN,因此與沒有員工刪除部門。

+0

感謝您的解釋,但我也有第二個查詢中的where子句..是否在子查詢中的where子句的行爲不同? – bmsqldev

+1

由於where子句位於子查詢中,因此它首先被應用,並且不會影響從'Department'檢索的行,因此而不是指示「獲取部門和員工的所有組合,然後只留下部門匹配的那些」的指令,你實際上是在說「給我所有部門的記錄,併爲每個部門獲取所有匹配的員工記錄」。 – GarethD

2

您可以在部門和員工之間看到下面的計劃,用於您的第一個查詢外部申請。由於您的where子句,它被轉換爲內連接。 enter image description here

第二個查詢的執行計劃顯示部門和員工表之間的左外連接。在第二個查詢每個部門時,如果沒有員工提出子查詢,則檢查員工將返回空值。

但在第一個含有NULL值的查詢行中,由於您的where子句而被刪除。

在圖像'e'和'd'是employeedepartment表。

enter image description here

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更詳細地解釋了上述內容。

的應用操作,也可以與table value constructor結合通過其他方法返回完全相同的結果:

-- Using TVC. 
SELECT 
    st.Number, 
    ad.Result 
FROM 
    @SampleTable AS st 
     CROSS APPLY 
      (
       VALUES 
        (st.Number + 1) 
      ) AS ad(Result) 
; 

這種強大的技術可以讓您對您的數據進行計算,並給出結果的別名。

當涉及到應用操作符時,這個答案几乎沒有劃傷表面。它有更多的技巧。我強烈建議進一步研究。

相關問題