APPLY 运算符
使用 APPLY 运算符(2005或以上版本)可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。
APPLY 有两种形式: CROSS APPLY 和 OUTER APPLY。
CROSS APPLY 仅返回外部表中通过表值函数生成结果集的行。
OUTER APPLY 既返回生成结果集的行,也返回不生成结果集的行,其中表值函数生成的列中的值为 NULL。
语法:
<left_table_expression> {cross|outer} apply <right_table_expression>
为了更好理解这两种格式,下面来演示一下
测试#table_name数据如下,list字段的数字代表一门选修课,每个人可以选择多门选修课程,我们需要计算每门选修课被选中的比例,当被选修的课程比例超过50%就开设该课程,否则不开
我的解决思路是,把表#table_name中的list字段作为参数参入一个函数将字符分割返回然后利用聚合函数求每门课程被选中的次数,如何将表中的字段作为参数参入函数并返回了? 当然是利用 APPLY了
--分割函数 create function Split(@input Varchar(max), @Split Varchar(99)) returns table as Return with Split_table(List_split, List , lever) as ( select @input ,@input, 0 as lever union all select LEFT(List, CHARINDEX(@Split,List+@Split)-1), STUFF(List, 1, CHARINDEX(@Split,List+@Split), ''), 1 from Split_table where List <> '' ) select List_split from Split_table where lever=1 --通过 cross apply将表中list字段作为参数传入Split函数中
select List_split,count(1)Ct from #table_name cross apply dbo.Split (list, ',') group by List_split
我们来看看cross apply 与outer apply的区别
select * from #table_name cross apply dbo.Split (list, ',')
select * from #table_name outer apply dbo.Split (list, ',')
大家看出OUTER APPLY和CROSS APPLY的区别了吧。
cross apply 与 outer apply 的区别就好像left join 与 join 的区别。如果 apply 不生成行,outer apply 也会返回该行,而 cross apply 则不会输出该行。
APPLY的执行过程,它先逻辑计算左表表达式(以上的LargeTable表),然后把右表达式(以上的自定义表值函数Split)应用到左表表达式的每一行。实际是把外部查询的列引用作为参数传递给表值函数