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,因为 order d.id desc 只会给出第一个 id,即 30,然后它应该返回 dept id = 30 的员工,但它给了我所有行以及所有部门。
查询出了什么问题,或者我错误地解释了交叉应用的概念。
最佳答案
你说“在上面的查询中,我假设它应该只需要 dept=30,因为 order d.id desc 只会给出第一个 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
子句选择
列ORDER BY
子句TOP
运算符
请注意,在您的内部查询中,TOP
运算符将last 应用,远在 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
此处,已使用另一个嵌套子查询对逻辑进行了重新排序,以确保先应用 ORDER BY
,然后再应用 TOP 1
。 WHERE
子句。 (请注意,这通常不是推荐的方法,因为嵌套子查询可能会妨碍可读性,我只是在这里使用它来保留 CROSS APPLY
并保留原始结构的其余部分)。
关于SQL Server 交叉应用不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20612958/