我正在尝试使用两种不同的方法获得相同的结果,但看来 我在某处做错了,我无法弄清
使用innerjoin的第一个查询:
with cte as(
select *, ROW_NUMBER() OVER(ORDER BY businessentityid desc) AS Row#
from HumanResources.Employee
)
Select A.firstname, B.jobtitle
from Person.Person A
inner join cte B on A.BusinessEntityID = B.BusinessEntityID and B.Row# <= 3
具有交叉应用的第二个查询:
Select A.firstname, cte.jobtitle
from Person.Person A
cross apply
(
Select top 3 *
from HumanResources.Employee B
where B.BusinessEntityID= A.BusinessEntityID
order by businessentityid DESC
) cte
有两种不同的结果,有什么想法
更新:
感谢@PriyankJ给了我这个主意,我设法找到了正确的查询,从而得到了想要的结果:
SELECT **top 3** cte.FirstName ,B.JobTitle
FROM **HumanResources.Employee B**
CROSS APPLY
(
SELECT TOP 3 *
FROM **person.person A**
WHERE A.BusinessEntityID = B.BusinessEntityID
ORDER BY
A.BusinessEntityID DESC
) cte
更改(第一个查询与第二个查询之间的差异)被突出显示:)
答案 0 :(得分:2)
我认为交叉应用左表必须为HumanResources.Employee
才能获得相同的结果。
SELECT TOP 3
cte.firstname
,A.jobtitle
FROM HumanResources.Employee A
CROSS APPLY (SELECT
*
FROM Person.Person B
WHERE B.BusinessEntityID = A.BusinessEntityID) cte
ORDER BY cte.BusinessEntityID DESC
答案 1 :(得分:1)
所以你问'为什么'。这可能会有所帮助。
重要的是要更好地了解JOIN和CROSS APPLY的实际作用。
考虑以下架构:
DECLARE @Person as Table (BusinessEntityID int, firstname varchar(10))
DECLARE @Employee as Table (BusinessEntityID int, jobtitle varchar(10))
INSERT INTO @Person (BusinessEntityID, firstname) Values
(1,'Annie'), (2,'Brad'), (3,'Coraline'), (4,'David')
INSERT INTO @Employee (BusinessEntityID, jobtitle) Values
(1,'Director'), (2,'Manager'), (3,'Analyst'), (4,'Gopher')
第一个查询
with cte as(
select *, ROW_NUMBER() OVER(ORDER BY businessentityid desc) AS Row#
from @Employee
)
Select A.firstname, B.jobtitle
from @Person A
inner join cte B on A.BusinessEntityID = B.BusinessEntityID and B.Row# <= 3
哪个返回此:
firstname jobtitle
---------- ----------
Brad Manager
Coraline Analyst
David Gopher
您的CTE被BusinessEntityID(降序)限制为前3个记录。所以安妮不在那。然后,我们执行内部联接,该联接返回两个组中与联接列匹配的所有记录。因此,Employee表中的Director掉了出来,我们的最终集合是3条记录。但是交叉申请在做什么?
Select A.firstname, cte.jobtitle
from @Person A
cross apply
(
Select top 3 *
from @Employee B
where B.BusinessEntityID= A.BusinessEntityID
order by businessentityid DESC
) cte
firstname jobtitle
---------- ----------
Annie Direcor
Brad Manager
Coraline Analyst
David Gopher
这是不同的。 CROSS APPLY与联接列上的两个集合不匹配。 相反,它会评估左侧每一行的右侧。 Person中有四行,对于每一项,Cross Apply将从Employee中选择前3条记录,这些记录将与BusinessEntityID上的该行匹配(由于where子句)。这将给您4行。让我们稍微更改一下Employee表。
INSERT INTO @Employee (BusinessEntityID, jobtitle) Values
(1,'Direcor'),(2,'Manager'),(3,'Analyst'),(4,'Gopher'),(4,'Blacksmith')
我们添加了具有重复实体ID的铁匠。我们得到什么?
加入逻辑
firstname jobtitle
---------- ----------
Coraline Analyst
David Gopher
David Blacksmith
交叉应用逻辑
firstname jobtitle
---------- ----------
Annie Direcor
Brad Manager
Coraline Analyst
David Gopher
David Blacksmith
我们看到,在加入的CTE中,重复的ID已将我们较小的ID之一从前3个BusinessEntityId列表中排除,而David在重复的ID处出现了两次。
在交叉应用中,我们有来自Person的四行,以及来自Employee的前三行,它们与person的每一行都匹配。在BusinessEntityID = 4的情况下,有两个匹配项,我们都得到了它们。
最重要的一点是,Cross apply在左侧的每一行的上下文中评估右侧。联接只是返回匹配的行。
如果您希望交叉联接查询模仿内部联接可以创建的相同“过滤”效果,则必须将要限制的表放在交叉联接的左侧。
;with cte as(
select *, ROW_NUMBER() OVER(ORDER BY businessentityid desc) AS Row#
from @Employee
)
Select A.firstname, B.jobtitle
from cte B
cross join @Person A
where A.BusinessEntityID = B.BusinessEntityID and B.Row# <= 3
firstname jobtitle
---------- ----------
David Gopher
David Blacksmith
Coraline Analyst
答案 2 :(得分:0)
您需要的是“外部申请”。试试这个:
Select A.firstname, cte.jobtitle
from Person.Person A
outer apply
(
Select top 3 *
from HumanResources.Employee B
where B.BusinessEntityID= A.BusinessEntityID
order by businessentityid DESC
) cte
答案 3 :(得分:0)
最重要的是为什么要使用CROSS APPLY
或INNER JOIN
?
您可以通过这种方式尝试
Select A.firstname, cte.jobtitle
from Person.Person A
cross apply
(
Select * from
(
Select top 3 *
from HumanResources.Employee B
order by businessentityid DESC
)B
where B.BusinessEntityID= A.BusinessEntityID
) cte
现在,您可以轻松了解为什么得到不同的结果。