T-SQL学习记录:Cross Apply与Outer Apply学习

浏览: 2312
SQL

引言:

SQL学习时,发现T-SQL还有Cross Apply和Outer  Apply功能,以前从未接触过,查了一些资料:http://www.2cto.com/database/201304/206330.html

然后发现Oracle在12c的新版本上也引入了Cross Apply和Outer Apply,而Cross Apply和Outer Apply可以用inner join和left join改写。

知识点:

apply语法:<left_table_expression>  {cross|outer} apply <right_table_expression>

apply运算涉及的两个步骤: 

A1:把右表表达式(<right_table_expression>)应用到左表(<left_table_expression>)输入的行;

A2:添加外部行;

使用apply就像是先计算左输入,让后为左输入中的每一行计算一次右输入。

Cross Apply原SQL:

with Customers as
(
select 'FISSA' as customerid,'Madrid' as city union all
select 'FRNDO','Madrid' union all
select 'KRLOS','Madrid' union all
select 'MRPHS','Zion' union all
select 'Choc','Beijing'
),
Orders as
(select 1 as orderid,'FRNDO' as customerid union all
select 2,'FRNDO' union all
select 3,'KRLOS' union all
select 4,'KRLOS' union all
select 5,'KRLOS' union all
select 6,'MRPHS' union all
select 7,null union all
select 8,'KRLOS' union all
select 9,'KRLOS' union all
select 10,'FRNDO'
)
select *
from Customers as C
cross apply
(select top 2 *
from Orders as O
where C.customerid=O.customerid
order by orderid desc) as CA

Cross Apply查询结果.JPG

Cross Apply过程分析:

  先得出左表【Customers】里的数据,然后把此数据一条一条的放入右表表式中,分别得出结果集,最后把结果集整合到一起就是最终的返回结果集了(T1的数据像for循环一样 一条一条的进入到T2中 然后返回一个集合,最后把所有的集合整合到一块就是最终的结果)。

  最后我们再理解一下:使用apply就像是先计算左输入,然后为左输入中的每一行计算一次右输入。

Cross Apply改写为inner join

with Customers as
(
select 'FISSA' as customerid,'Madrid' as city union all
select 'FRNDO','Madrid' union all
select 'KRLOS','Madrid' union all
select 'MRPHS','Zion' union all
select 'Choc','Beijing'
),
Orders as
(select 1 as orderid,'FRNDO' as customerid union all
select 2,'FRNDO' union all
select 3,'KRLOS' union all
select 4,'KRLOS' union all
select 5,'KRLOS' union all
select 6,'MRPHS' union all
select 7,null union all
select 8,'KRLOS' union all
select 9,'KRLOS' union all
select 10,'FRNDO'
)
select *
from Customers as C
inner join Orders as O
on O.orderid in (select top 2 orderid
from Orders as O
where C.customerid=O.customerid
order by orderid desc)

inner join查询结果.JPG

Outer Apply:

with Customers as
(
select 'FISSA' as customerid,'Madrid' as city union all
select 'FRNDO','Madrid' union all
select 'KRLOS','Madrid' union all
select 'MRPHS','Zion' union all
select 'Choc','Beijing'
),
Orders as
(select 1 as orderid,'FRNDO' as customerid union all
select 2,'FRNDO' union all
select 3,'KRLOS' union all
select 4,'KRLOS' union all
select 5,'KRLOS' union all
select 6,'MRPHS' union all
select 7,null union all
select 8,'KRLOS' union all
select 9,'KRLOS' union all
select 10,'FRNDO'
)
select *
from Customers as C
outer apply
(select top 2 *
from Orders as O
where C.customerid=O.customerid
order by orderid desc) as CA
;

Outer Apply查询结果.JPG

Outer Apply过程分析:发现outer apply得到的结果比cross apply多了两行。cross apply和outer apply 总是包含步骤A1,只有outer apply包含步骤A2。如果cross apply左行应用右表表达式时返回空积,则不返回该行。而outer apply返回该行。

Outer Apply改写为left join:

with Customers as
(
select 'FISSA' as customerid,'Madrid' as city union all
select 'FRNDO','Madrid' union all
select 'KRLOS','Madrid' union all
select 'MRPHS','Zion' union all
select 'Choc','Beijing'
),
Orders as
(select 1 as orderid,'FRNDO' as customerid union all
select 2,'FRNDO' union all
select 3,'KRLOS' union all
select 4,'KRLOS' union all
select 5,'KRLOS' union all
select 6,'MRPHS' union all
select 7,null union all
select 8,'KRLOS' union all
select 9,'KRLOS' union all
select 10,'FRNDO'
)
select *
from Customers as C
left join Orders as O
on O.orderid in (select top 2 orderid
from Orders as O
where C.customerid=O.customerid
order by orderid desc)

left join查询结果.JPG

个人结论:用Cross Apply,Outer Apply的SQL更简洁,查看执行计划,我理解执行效率应该更高些。





推荐 1
本文由 choc 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

4 个评论

SQL代码可以用代码的格式,帮你调整了下。记得上传一张照片了,个人设置,头像,看起来专业一些,哈哈
choc

choc 回复 梁勇

有劳了,我主要记录给自己用,这儿很方便记录哦。
梁勇

梁勇 回复 choc

方便的,哈哈,博客功能很有用的。
这个功能挺不错的,之前用过

要回复文章请先登录注册