小编典典

我什么时候应该使用 CROSS APPLY 而不是 INNER JOIN?

all

使用CROSS APPLY的主要目的是什么?

我已经阅读(模糊地,通过 Internet 上的帖子),cross apply如果您正在分区,则在选择大型数据集时可能会更有效。(想到分页)

我也知道CROSS APPLY不需要 UDF 作为右表。

在大多数INNER JOIN查询(一对多关系)中,我可以将它们重写为 use CROSS APPLY,但它们总是给我等效的执行计划。

谁能给我一个很好的例子,说明什么时候CROSS APPLY在那些INNER JOIN也能起作用的情况下有所作为?


编辑:

这是一个简单的示例,其中执行计划完全相同。(告诉我它们的不同之处以及cross apply更快/更高效的地方)

create table Company (
    companyId int identity(1,1)
,   companyName varchar(100)
,   zipcode varchar(10) 
,   constraint PK_Company primary key (companyId)
)
GO

create table Person (
    personId int identity(1,1)
,   personName varchar(100)
,   companyId int
,   constraint FK_Person_CompanyId foreign key (companyId) references dbo.Company(companyId)
,   constraint PK_Person primary key (personId)
)
GO

insert Company
select 'ABC Company', '19808' union
select 'XYZ Company', '08534' union
select '123 Company', '10016'


insert Person
select 'Alan', 1 union
select 'Bobby', 1 union
select 'Chris', 1 union
select 'Xavier', 2 union
select 'Yoshi', 2 union
select 'Zambrano', 2 union
select 'Player 1', 3 union
select 'Player 2', 3 union
select 'Player 3', 3


/* using CROSS APPLY */
select *
from Person p
cross apply (
    select *
    from Company c
    where p.companyid = c.companyId
) Czip

/* the equivalent query using INNER JOIN */
select *
from Person p
inner join Company c on p.companyid = c.companyId

阅读 89

收藏
2022-02-28

共1个答案

小编典典

谁能给我一个很好的例子,说明何时 CROSS APPLY 在 INNER JOIN 也可以工作的情况下有所作为?

详细性能对比见我博客中的文章:

CROSS APPLY在没有简单JOIN条件的事情上效果更好。

此选项从以下每条记录中选择3最后一条记录:t2``t1

SELECT  t1.*, t2o.*
FROM    t1
CROSS APPLY
        (
        SELECT  TOP 3 *
        FROM    t2
        WHERE   t2.t1_id = t1.id
        ORDER BY
                t2.rank DESC
        ) t2o

它不能很容易地用一个INNER JOIN条件来制定。

您可能可以使用CTE‘s 和 window 函数执行类似的操作:

WITH    t2o AS
        (
        SELECT  t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn
        FROM    t2
        )
SELECT  t1.*, t2o.*
FROM    t1
INNER JOIN
        t2o
ON      t2o.t1_id = t1.id
        AND t2o.rn <= 3

,但这不太可读,可能效率较低。

更新:

刚检查。

master``20,000,000是带有PRIMARY KEYon的 about 记录表id

这个查询:

WITH    q AS
        (
        SELECT  *, ROW_NUMBER() OVER (ORDER BY id) AS rn
        FROM    master
        ),
        t AS 
        (
        SELECT  1 AS id
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    t
JOIN    q
ON      q.rn <= t.id

运行几乎30几秒钟,而这个:

WITH    t AS 
        (
        SELECT  1 AS id
        UNION ALL
        SELECT  2
        )
SELECT  *
FROM    t
CROSS APPLY
        (
        SELECT  TOP (t.id) m.*
        FROM    master m
        ORDER BY
                id
        ) q

是瞬间的。

2022-02-28