[英]SQL Server cross apply not working?
http://sqlfiddle.com/#!3/78273/1
create table emptb1
(
id int,
name varchar(20),
dept int
)
insert into emptb1 values (1,'vish',10);
insert into emptb1 values (2,'vish',10);
insert into emptb1 values (3,'vish',30);
insert into emptb1 values (4,'vish',20);
create table depttb1
(
id int,
name varchar(20)
)
insert into depttb1 values(10,'IT')
insert into depttb1 values(20,'AC')
insert into depttb1 values(30,'LIC')
select * from emptb1
select e.id, e.name, a.id
from emptb1 e
cross apply
(
select top 1 * from depttb1 d
where d.id = e.dept
order by d.id desc
) a
我試圖學習交叉應用,因為它類似於內連接,但與函數一起工作。
在上面的查詢我假設它應該只采取dept = 30因為訂單d.id desc將只給出top的第一個id為30然后它應該返回dept id = 30的員工但是它給了我所有的行和所有的DEPTID。
查詢有什么問題,或者我錯誤地解釋了交叉申請的概念。
你說“ 在上面的查詢我假設它應該只采取dept = 30因為訂單d.id desc將只給出top的第一個id為30然后它應該返回dept id = 30的員工 ”。
這不是它的工作原理。 這是您的查詢(為了清晰起見,重新格式化了一點):
select e.id, e.name, a.id
from emptb1 e
cross apply
(
select top 1 *
from depttb1 d
where d.id = e.dept
order by d.id desc
) a
APPLY
關鍵字表示內部查詢(邏輯上)為外部查詢的每一行調用一次。 對於內部查詢中發生的事情,理解執行SELECT
子句的邏輯順序是有幫助的。這個順序是:
FROM
子句 WHERE
子句 SELECT
列 ORDER BY
子句 TOP
運營商 請注意,在內部查詢中, TOP
運算符最后應用於WHERE
子句之后。 這意味着where d.id = e.dept
將首先減小內行那些d.id
的匹配e.dept
外排的(這不一定是30),然后對它們進行排序,然后返回第一個。 它為外部查詢中的每一行執行此操作 。 顯然,他們中的許多人不會是30
。
你想要的更像是這個(仍然保留了CROSS APPLY
):
select e.id, e.name, a.id
from emptb1 e
cross apply
(
select top 1 *
from
(
select top 1 *
from depttb1 d
order by d.id desc
) b
where b.id = e.dept
) a
這里,邏輯已經通過使用另一個嵌套的子查詢進行了重新排序,該子查詢確保在WHERE
子句之前應用ORDER BY
,然后應用TOP 1
。 (請注意,這通常不建議這樣做,因為嵌套的子查詢會妨礙可讀性,我只是在這里使用它來保留CROSS APPLY
並保留原始結構的其余部分)。
為了誇大Damien的評論,內部查詢:
select top 1 * from depttb1 d
where d.id = e.dept
order by d.id desc
將在外部查詢中的每一行運行:
select e.id, e.name, a.id
from emptb1 e
因此,您將始終從每行的內部查詢中獲得匹配。 我認為你期望內部查詢只運行一次,但這不是APPLY
作用。
因此,從外部查詢的第一行開始,ID為1,dept id為10,您的內部查詢將轉換為:
select top 1 * from depttb1 d
where d.id = 10 //this is the dept id for the current row from your outer query
order by d.id desc
要在沒有交叉應用的情況下解決此問題,請使用子查詢。 但是在您的示例中,它只返回一行,最后一個部門輸入,假設id值正在增加。
-- Using a sub query to find max dept
select e.id, e.name
from emptb1 e
where e.dept in
(
select top 1 id
from depttb1
order by id desc
)
CROSS APPLY背后的想法有點像CROSS JOIN。 這將返回所有行。 它由DBA用於許多表值函數(TVF)的動態管理視圖(DMV)
你想要的是一個外部應用,有點像LEFT JOIN。
select e.id, e.name
from emptb1 e
outer apply
(
select top 1 d.id from depttb1 d order by d.id desc
) AS m (id)
where e.dept = m.id
查看我關於這些概念的文章。
交叉申請 - http://craftydba.com/?p=3767
外部申請 - http://craftydba.com/?p=3796
表值功能(內聯) - http://craftydba.com/?p=3733
表值功能(多行) - http://craftydba.com/?p=3754
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.