SQL Server交叉应用不起作用?

Reg*_*ser 5 sql sql-server sql-server-2008 cross-apply

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
Run Code Online (Sandbox Code Playgroud)

我试图学习交叉应用,因为它类似于内连接,但与函数一起工作.

在上面的查询我假设它应该只采取dept = 30因为订单d.id desc将只给出top的第一个id为30然后它应该返回dept id = 30的员工但是它给了我所有的行和所有的DEPTID.

查询有什么问题,或者我错误地解释了交叉申请的概念.

RBa*_*ung 9

你说" 在上面的查询我假设它应该只采取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
Run Code Online (Sandbox Code Playgroud)

APPLY关键字是指内部查询是(逻辑上)的外部查询的每一行调用一次.对于内部查询中发生的事情,理解SELECT执行a的子句的逻辑顺序是有帮助的.这个顺序是:

  1. FROM 条款
  2. WHERE 条款
  3. SELECT
  4. ORDER BY 条款
  5. TOP 操作者

请注意,在您的内部查询中,TOP操作符最后应用于该WHERE子句之后.这意味着where d.id = e.dept将首先将内部行减少到d.ide.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
Run Code Online (Sandbox Code Playgroud)

在这里,逻辑已被使用另一个嵌套子查询确保了的重新排序ORDER BY,然后TOP 1得到应用之前WHERE条款.(请注意,这通常不建议这样做,因为嵌套的子查询可能会妨碍可读性,我只是在这里使用它来保留CROSS APPLY并保留原始结构的其余部分).

  • 噢噢噢!我想我从这个答案中获得了我的秘密帽子!还是不知道为什么......? (2认同)