先说点题外话,因为后面我会用到这个函数。

前两天自定义了一个 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的更多相关文章

  1. SQL Server连接查询之Cross Apply和Outer Apply的区别及用法(转载)

    先简单了解下cross apply的语法以及会产生什么样的结果集吧!示例表: SELECT * FROM tableA CROSS APPLY tableB 两张表直接连接,不需要任何的关联条件,产生 ...

  2. CROSS APPLY AND CROSS APPLY

    随着业务千奇百怪,DBA数据库设计各有不同,一对多关系存JSON或字符串逗号分隔... 今天小编给大家分享一下针对这个问题的解决办法 问题一.存储过程接受参数格式为XXX,XXX 解决办法:将字符转成 ...

  3. 20、Outer Apply 和 Cross Apply

    1.場合 select...caseが複雑の時 2.運用方法 SELECT * FROM stu CROSS APPLY ( --like inner join * FROM score WHERE ...

  4. SQL Server中CROSS APPLY和OUTER APPLY的应用详解

    SQL Server数据库操作中,在2005以上的版本新增加了一个APPLY表运算符的功能.新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表达式都可以, ...

  5. sql server cross/outer apply 用法

    这是 sql server 帮助文档关于apply的描述: 使用 APPLY 运算符(2005或以上版本)可以为实现查询操作的外部表表达式返回的每个行调用表值函数.表值函数作为右输入,外部表表达式作为 ...

  6. <转>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 ...

  7. SQL Server中CROSS APPLY和OUTER APPLY应用

    1.什么是Cross Apply和Outer Apply ? 我们知道SQL Server 2000中有Cross Join用于交叉联接的.实际上增加Cross Apply和Outer Apply是用 ...

  8. SQL Server:APPLY表运算符

    SQL Server 2005(含)以上版本,新增了APPLY表运算,为我们日常查询带来了极大的方便. 新增的APPLY表运算符把右表表达式应用到左表表达式中的每一行.它不像JOIN那样先计算那个表表 ...

  9. CROSS APPLY vs OUTER APPLY

    Apply 工作原理:    Apply操作符让符合查询的每一条记录都调用一次TVF函数,并将结果与原数据表的记录内容一起展开.    Apply操作符定义在From子句内,使用方式与Join操作符类 ...

随机推荐

  1. Java并发编程从入门到精通 张振华.Jack --我的书

    [当当.京东.天猫.亚马逊.新华书店等均有销售] 目 录 第一部分:线程并发基础 第1章 概念部分   1 1.1 CPU核心数.线程数 (主流cpu.线程数的大体情况说一下) 1 1.2 CPU时间 ...

  2. 登陆Oracle11g的企业管理器

    本地:https://localhost:1158/em/ 如果远程:那么把localhost换成服务器IP

  3. GCC命令基础

    gcc命令使用GNU推出的基于C/C++的编译器,是开放源代码领域应用最广泛的编译器,具有功能强大,编译代码支持性能优化等特点, 现在很多程序员都应用GCC,怎样才能更好的应用GCC. 目前,GCC可 ...

  4. 第十三篇:K-Means 聚类算法原理分析与代码实现

    前言 在前面的文章中,涉及到的机器学习算法均为监督学习算法. 所谓监督学习,就是有训练过程的学习.再确切点,就是有 "分类标签集" 的学习. 现在开始,将进入到非监督学习领域.从经 ...

  5. 高级service之ipc ADIL用法

    感谢 如果你还没有看过前面一篇文章,建议先去阅读一下 Android Service完全解析,关于服务你所需知道的一切(上) ,因为本篇文章中涉及到的代码是在上篇文章的基础上进行修改的. 在上篇文章中 ...

  6. Oracle索引相关

    oracle的索引分为5种:唯一索引,组合索引,反向键索引,位图索引,基于函数的索引. 创建索引的标准语法: CREATE INDEX 索引名 ON 表名 (列名) TABLESPACE 表空间名; ...

  7. Android开源项目分类汇总【畜生级别】

    From :http://blog.csdn.net/forlong401/article/details/25459403?c=6c4cd677a617db4655988e41ee081691#t7 ...

  8. Struts入门(三)深入Struts用法讲解

    访问Servlet API Action搜索顺序 动态方法调用 指定多个配置文件 默认Action Struts 后缀 接收参数 处理结果类型 1.访问Servlet API 首先我们了解什么是Ser ...

  9. 用wamp实现前端和php的交互效果

    我们今天来用php来做一下前台与后台的交互效果,首先我们先打开这个软件. 看一下电脑右下角的小图标 当变成之后鼠标左键 打开这个之后点击第二个之后会打开一个网站 点击右面页面的数据库打开新建数据库,填 ...

  10. 跟着包子学 css (一)

    1.在每次 写css之前 都应该先将浏览器的默认 样式 给清除掉 *{padding:0; margin:0;} h1,h2,h3,h4,h5,h6{font-weight:normal; font- ...