使用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
交叉应用也适用于XML字段。如果您希望结合其他字段选择节点值。
例如,如果您有一个包含一些xml的表
根> <
< subnode1 >
<some_node value="1" />
<some_node value="2" />
<some_node value="3" />
<some_node value="4" />
< / subnode1 >
根> < /
使用查询
SELECT
id as [xt_id]
,xmlfield.value('(/root/@attribute)[1]', 'varchar(50)') root_attribute_value
,node_attribute_value = [some_node].value('@value', 'int')
,lt.lt_name
FROM dbo.table_with_xml xt
CROSS APPLY xmlfield.nodes('/root/subnode1/some_node') as g ([some_node])
LEFT OUTER JOIN dbo.lookup_table lt
ON [some_node].value('@value', 'int') = lt.lt_id
将返回一个结果
xt_id root_attribute_value node_attribute_value lt_name
----------------------------------------------------------------------
1 test1 1 Benefits
1 test1 4 FINRPTCOMPANY
谁能给我一个很好的例子,CROSS APPLY在那些INNER JOIN也能工作的情况下发挥作用?
查看我博客上的文章,了解详细的性能比较:
内连接与交叉应用
CROSS APPLY在没有简单JOIN条件的情况下工作得更好。
它为t1中的每条记录从t2中选择3条最后的记录:
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连接条件来表述。
你可以使用CTE和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条记录的表,id上有一个PRIMARY KEY。
这个查询:
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
是即时的。