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

我已经读到(模糊地,通过互联网上的帖子),如果您正在分区,那么在选择大型数据集时,交叉应用可以更有效。(想到寻呼)

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

在大多数INNER JOIN查询(一对多关系)中,我可以使用CROSS APPLY重写它们,但它们总是给我相同的执行计划。

谁能给我一个很好的例子,CROSS APPLY在那些INNER JOIN也能工作的情况下发挥作用?


编辑:

这里有一个简单的例子,其中执行计划完全相同。(告诉我一个它们的不同之处,交叉应用在哪里更快/更有效)

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

当前回答

我们使用CROSS APPLY从另一个(更新请求)表中使用JSON更新一个表—join不能用于此,因为我们使用OPENJSON来读取JSON的内容,而OPENJSON是一个“表值函数”。

我本打算在这里放一个简化版的UPDATE命令作为示例,但即使是简化了,作为一个示例,它也太大、太复杂了。因此,这个简单的命令部分“草图”就足够了:

SELECT  
       r.UserRequestId,
       j.xxxx AS xxxx,
FROM  RequestTable as r WITH (NOLOCK)
   CROSS APPLY
      OPENJSON(r.JSON, '$.requesttype.recordtype')
      WITH(
             r.userrequestid nvarchar(50) '$.userrequestid',
             j.xxx nvarchar(20) '$.xxx
           )j
       WHERE r.Id > @MaxRequestId
          and ... etc. ....

其他回答

当你需要子查询的列时,交叉应用可以用来替换子查询

子查询

select * from person p where
p.companyId in(select c.companyId from company c where c.companyname like '%yyy%')

在这里,我将无法选择公司表的列 使用交叉应用

select P.*,T.CompanyName
from Person p
cross apply (
    select *
    from Company C
    where p.companyid = c.companyId and c.CompanyName like '%yyy%'
) T

这可能是一个老问题,但我仍然喜欢CROSS APPLY的强大功能,它简化了逻辑的重用,并为结果提供了一种“链接”机制。

我在下面提供了一个SQL Fiddle,它展示了一个简单的示例,说明如何使用CROSS APPLY对数据集执行复杂的逻辑操作,而不会让事情变得一团糟。从这里不难推断出更复杂的计算。

http://sqlfiddle.com/ !3/23862/2

APPLY操作符的本质是允许在FROM子句中操作符的左右侧之间进行关联。

与JOIN相比,输入之间的相关性是不允许的。

说到APPLY运算符中的相关性,我的意思是在右边我们可以写:

派生表——作为具有别名的相关子查询 表值函数——一个带有参数的概念视图,其中参数可以指向左侧

两者都可以返回多列和多行。

我们使用CROSS APPLY从另一个(更新请求)表中使用JSON更新一个表—join不能用于此,因为我们使用OPENJSON来读取JSON的内容,而OPENJSON是一个“表值函数”。

我本打算在这里放一个简化版的UPDATE命令作为示例,但即使是简化了,作为一个示例,它也太大、太复杂了。因此,这个简单的命令部分“草图”就足够了:

SELECT  
       r.UserRequestId,
       j.xxxx AS xxxx,
FROM  RequestTable as r WITH (NOLOCK)
   CROSS APPLY
      OPENJSON(r.JSON, '$.requesttype.recordtype')
      WITH(
             r.userrequestid nvarchar(50) '$.userrequestid',
             j.xxx nvarchar(20) '$.xxx
           )j
       WHERE r.Id > @MaxRequestId
          and ... etc. ....

交叉应用有时可以让您做一些内部连接无法做到的事情。

示例(语法错误):

select F.* from sys.objects O  
inner join dbo.myTableFun(O.name) F   
on F.schema_id= O.schema_id

这是一个语法错误,因为当与内部连接一起使用时,表函数只能接受变量或常量作为参数。(也就是说,表函数参数不能依赖于另一个表的列。)

然而:

select F.* from sys.objects O  
cross apply ( select * from dbo.myTableFun(O.name) ) F  
where F.schema_id= O.schema_id

这是合法的。

编辑: 或者,更短的语法:(通过ErikE)

select F.* from sys.objects O  
cross apply dbo.myTableFun(O.name) F
where F.schema_id= O.schema_id

编辑:

注意: Informix 12.10 xC2+有横向派生表,Postgresql(9.3+)有横向子查询,可以达到类似的效果。