[英]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.