簡體   English   中英

SQL Server交叉應用不起作用?

[英]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子句的邏輯順序是有幫助的。這個順序是:

  1. FROM子句
  2. WHERE子句
  3. SELECT
  4. ORDER BY子句
  5. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM