SQL Server outer apply 和 cross apply
先说点题外话,因为后面我会用到这个函数。
前两天自定义了一个 sql 的字符串分割函数(Split),不过后来发现有点问题,例如:
select * from Split(default,'123,456,,,,789,')

我之前只处理了截取的最后一个为空的字符串,所以会出现以上的结果,现在我做了一些修改。代码如下:
USE [Test]
GO
/****** Object: UserDefinedFunction [dbo].[Split] Script Date: 2017/4/16 22:05:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Split](@separator VARCHAR(64)=',',@string NVARCHAR(max))
RETURNS @ResultTab TABLE (
Id INT ,
Res NVARCHAR(500)
)
AS
BEGIN
DECLARE @Num INT
DECLARE @Str nvarchar(500) IF(@string IS NOT NULL AND @string <> '' AND LEN(@string)>0)
BEGIN
IF(CHARINDEX(@separator,@string)>0) --判断要截取的字符是否存在
BEGIN
SET @Num=0
WHILE (CHARINDEX(@separator,@string)>0) --如果要截取的字符存在,就继续循环
BEGIN
SET @Num=@Num+1
set @Str=LEFT(@string,CHARINDEX(@separator,@string)-1)
27
28 if(@Str is not null and @Str <> '') --做一下判断,如果截取的字符串为空就不插入返回结果的表
29 begin
30 INSERT INTO @ResultTab(Id,Res) --截取字符串,插入表变量
31 SELECT @Num,@Str
32 end
33 else
34 begin
35 set @Num=@Num-1
36 end --把已经截取并插入的字符串删除
SET @string=STUFF(@string,1,CHARINDEX(@separator,@string)-1+LEN(@separator),'')
END --如果最后一个截取的字符串为空,那就不插入了
--例如:'123,456,789,' 这样的字符串最后剩下的就是空字符串了
IF(@string IS NOT NULL AND @string <> '')
BEGIN
INSERT INTO @ResultTab(Id,Res)
SELECT @Num+1,@string
END
END
ELSE
BEGIN
DELETE FROM @ResultTab
END
END
ELSE
BEGIN
DELETE FROM @ResultTab
END
RETURN
END
红色部分的代码为添加或修改的部分,下面再看一下效果。
select * from Split(default,'123,456,,,,789,321,,,')

之前自定义 Split 函数时我还觉得不能直接作用于表,不过今天了解到一个方法,让我觉得或许可以实现。
APPLY 运算符:
使用 APPLY 运算符(2005或以上版本)可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。
APPLY 有两种形式: CROSS APPLY 和 OUTER APPLY。CROSS APPLY 仅返回外部表中通过表值函数生成结果集的行。OUTER APPLY 既返回生成结果集的行,也返回不生成结果集的行,其中表值函数生成的列中的值为 NULL。
语法:
<left_table_expression> {cross|outer} apply <right_table_expression>
先看看示例所用的数据:


现在有两个表,一个用户信息表和一个操作权限表,下面通过示例看看 apply 运算符有什么作用。
CROSS APPLY :
select * from UserInfo u
cross apply dbo.Split(default,u.P_Id)

最后两列为使用 cross apply 连接表值函数 Split 分割字段 P_Id 的值。下面如果我们要查询操作权限的名称呢?
select t.U_Id,t.U_No,t.U_Name,t.U_Pwd,t.P_Id,p.P_Id,p.P_Name,p.P_Remark from (
select * from UserInfo u
cross apply dbo.Split(default,u.P_Id))t
left join OperatePower p on t.Res=p.P_Id

OUTER APPLY:
select * from UserInfo u
outer apply dbo.Split(default,u.P_Id) select t.U_Id,t.U_No,t.U_Name,t.U_Pwd,t.P_Id,p.P_Id,p.P_Name,p.P_Remark from (
select * from UserInfo u
outer apply dbo.Split(default,u.P_Id))t
left join OperatePower p on t.Res=p.P_Id


可以看到 OUTER APPLY 返回的数据比 CORSS APPLY 返回的数据要多一行,这是因为,CORSS APPLY 只是返回能够匹配上的,而 OUTER APPLY 会返回所有的,不管能不能匹配上,不能匹配的就返回空(null)。
当然,OUTER APPLY 和 CORSS APPLY 还可以作用于表之间的连接:
create table #T(姓名 varchar(10))
insert into #T values('张三')
insert into #T values('李四')
insert into #T values(NULL ) create table #T2(姓名 varchar(10) , 课程 varchar(10) , 分数 int)
insert into #T2 values('张三' , '语文' , 74)
insert into #T2 values('张三' , '数学' , 83)
insert into #T2 values('张三' , '物理' , 93)
insert into #T2 values(NULL , '数学' , 50) select * from #T a
cross apply (select 课程,分数 from #t2 where 姓名=a.姓名) b select * from #T a
outer apply (select 课程,分数 from #t2 where 姓名=a.姓名) b

参考:
http://www.cnblogs.com/qixuejia/p/3960904.html
SQL Server outer apply 和 cross apply的更多相关文章
- SQL Server连接查询之Cross Apply和Outer Apply的区别及用法(转载)
先简单了解下cross apply的语法以及会产生什么样的结果集吧!示例表: SELECT * FROM tableA CROSS APPLY tableB 两张表直接连接,不需要任何的关联条件,产生 ...
- CROSS APPLY AND CROSS APPLY
随着业务千奇百怪,DBA数据库设计各有不同,一对多关系存JSON或字符串逗号分隔... 今天小编给大家分享一下针对这个问题的解决办法 问题一.存储过程接受参数格式为XXX,XXX 解决办法:将字符转成 ...
- 20、Outer Apply 和 Cross Apply
1.場合 select...caseが複雑の時 2.運用方法 SELECT * FROM stu CROSS APPLY ( --like inner join * FROM score WHERE ...
- SQL Server中CROSS APPLY和OUTER APPLY的应用详解
SQL Server数据库操作中,在2005以上的版本新增加了一个APPLY表运算符的功能.新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表达式都可以, ...
- sql server cross/outer apply 用法
这是 sql server 帮助文档关于apply的描述: 使用 APPLY 运算符(2005或以上版本)可以为实现查询操作的外部表表达式返回的每个行调用表值函数.表值函数作为右输入,外部表表达式作为 ...
- <转>SQL Server CROSS APPLY and OUTER APPLY
Problem SQL Server 2005 introduced the APPLY operator, which is like a join clause and it allows joi ...
- SQL Server中CROSS APPLY和OUTER APPLY应用
1.什么是Cross Apply和Outer Apply ? 我们知道SQL Server 2000中有Cross Join用于交叉联接的.实际上增加Cross Apply和Outer Apply是用 ...
- SQL Server:APPLY表运算符
SQL Server 2005(含)以上版本,新增了APPLY表运算,为我们日常查询带来了极大的方便. 新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表 ...
- CROSS APPLY vs OUTER APPLY
Apply 工作原理: Apply操作符让符合查询的每一条记录都调用一次TVF函数,并将结果与原数据表的记录内容一起展开. Apply操作符定义在From子句内,使用方式与Join操作符类 ...
随机推荐
- apacheserver全局配置具体解释
server标识相关指令: ServerName ServerAdmin ServerSignature ServerTokens UseCanonicalName UseCanonicalPhysi ...
- DM8168 OpenCV尝试与评估(编译ARM版OpenCV)
交叉编译opencv2.3.1,并在DM8168 cortex A8中执行图像处理. 开发环境: PC:ubuntu12.04LTS.Intel Core 2 Duo CPU E7200@2. ...
- iOS开发之-- textview 光标起始位置偏移
使用textview的时候,会发生光标偏移的情况,其实是因为iOS7里导航栏,状态栏等有个边缘延伸的效果在. 把边缘延伸关掉就好了.代码如下 //取消iOS7的边缘延伸效果(例如导航栏,状态栏等等) ...
- iOS开发之--苹果个人开发者账号如何升级成公司账号
1.拨打苹果针对中国区开发者的咨询服务热线:4006 701 855 2.简单向对方(中文不太标准,但听懂没问题)说明意图后,会要求提供: (1)之前申请IDP时purchase form上的pers ...
- 1808:公共子序列 即POJ 1458 Common Subsequence
1808:公共子序列 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 我们称序列Z = < z1, z2, ..., zk >是序列X = < ...
- centos中调整tmpfs分区的大小
tmpfs是Linux/Unix系统上的一种基于内存的文件系统.tmpfs可以使用系统的内存或swap分区来存储文件.由此可见,tmpfs主要存储暂存的文件. tmpfs默认的大小是RM的一半,假如你 ...
- ORA-28000: the account is locked
1.用system账号登录 2.执行一下sql: ALTER USER username ACCOUNT UNLOCK; 此处username 可能为scott或者你要解锁的用户名. ........ ...
- 获取 js DOM元素中绑定的所有事件,模仿 chrome getEventListeners
偶尔看到了这个问题,如何用JS获取元素某一事件上绑定的所有Listener? 突然觉得好像是有解决办法的,查了下,在 chrome 下,支持 window.getEventListeners(obj) ...
- Code Forces 644A Parliament of Berland
A. Parliament of Berland time limit per test1 second memory limit per test256 megabytes inputstandar ...
- web安全之xss攻击
xss攻击的全称是Cross-Site Scripting (XSS)攻击,是一种注入式攻击.基本的做法是把恶意代码注入到目标网站.由于浏览器在打开目标网站的时候并不知道哪些脚本是恶意的,所以浏览器会 ...