以前一直没有注意到apply这个05新特性的使用,最近看到一本书介绍此功能,发现这个功能是真香啊。
让一下测试用例说明一下
declare @supplier table(supid int, supname varchar(50))
insert into @supplier(supid,supname)
select 1,'华为' union all
select 2,'苹果' union all
select 3,'小米'
declare @products table(supid int,proid int,proname varchar(500),retailprice int)
insert into @products
select 2,1,'苹果12',5000 union all
select 2,2,'苹果11',4000 UNION ALL
SELECT 2,3,'A苹果10',3000 UNION ALL
SELECT 1,1,'MATE40',5000 UNION ALL
SELECT 1,2,'MATE30',4000
我想查出 每个供应商 零售价最高的二款产品,如果这个供应商没有供货则以null显示
窗口函数实现
select * from (
select a.supid,a.supname,b.proid,b.proname,b.retailprice,ROW_NUMBER()over(partition by b.supid order by retailprice desc ) as crd
from @supplier a
left join @products b on a.supid = b.supid) lt
where crd <= 2
order by supid,retailprice desc
outer apply 实现
select * from @supplier a
outer apply (select top 2 proid,proname,retailprice from @products b where a.supid = b.supid order by retailprice desc) as lt
order by a.supid,lt.retailprice desc
如果没有供货的供应商不显示 如图
窗口函数实现
select * from (
select a.supid,a.supname,b.proid,b.proname,b.retailprice,ROW_NUMBER()over(partition by b.supid order by retailprice desc ) as crd
from @supplier a
inner join @products b on a.supid = b.supid) lt
where crd <= 2
order by supid,retailprice desc
cross apply
select * from @supplier a
cross apply (select top 2 proid,proname,retailprice from @products b where a.supid = b.supid order by retailprice desc) as lt
order by a.supid,lt.retailprice desc
通过窗口函数的对比,相信大家也理解到了 outer apply与cross apply 的区别
cross apply 会将右表的每一行数据和左表关联的行一一对应 如果右表为null 则左表数据也不显示
outer apply也会 将右表的每一行数据和左表关联的行一一对应 如果右表为nul 则右表以null显示。
apply 语法,还有一种用法。就是拆分列以字符串拼成的"1,3,4" 这种,拆成行的功能, 只需要写一个字符拆分函数,然后 apply 这个函数 。