本文接上文:T-SQL 中的CROSS JOIN用法(半翻译) 同样可用于微软认证70-461: Querying Microsoft SQL Server 2012考试的学习中。
---------------------------------------------------------------------以下为译文-----------------------------------------------------------------------
原文出处:http://www.sqlservercentral.com/articles/Stairway+Series/121318/
从SQL Server 2005开始,微软添加了一个新的运算符用于关联一个带有函数的结果集,并把函数应用于表/视图中的每一个限定行中。这个运算符就是APPLY。从技术上来说,这个操作的底层逻辑并不是实际的“JOIN”,但由于它的用法更像是JOIN,所以通常会与关联操作相关联。APPLY操作分为两种格式:CROSS APPLY或OUTER APPLY。在本文中会分别展示这两种格式。
APPLY 简介:
你是否曾经写过SELECT语句去调用一个表值函数或把表值表达式的每一个记录与表匹配?如果有过这样的经历,APPLY运算符会帮到你。APPLY分为CROSS APPLY和OUTER APPLY。
第一种格式叫CROSS APPLY。它从CROSSAPPLY的一边提取表或数据集的每行的所需列值,然后作为输入值传输到另外一边的表值函数或表达式中。然后把所有关联的值使用UNION ALL运算符合并。如果表值函数针对输入数据没有满足调用条件时,函数将不返回输出,并且这部分的表或结果集将不会出现在最终结果中,因为它不能与表值函数的数据关联。
第二种格式叫OUTER APPLY。其行为和CROSSAPPLY类似,但返回不能调用表值函数/表达式的值。
为了更好理解这两种格式,下面来演示一下:
测试数据和函数:
USE tempdb; GO IF object_id('dbo.Product') IS NOT NULL DROP TABLE dbo.Product; IF object_id('dbo.SearchString') IS NOT NULL DROP TABLE dbo.SearchString; IF object_id('dbo.FindProductLike') IS NOT NULL DROP FUNCTION dbo.FindProductLike; CREATE TABLE dbo.Product ( ID INT IDENTITY , ProductNameVARCHAR(100) , Price MONEY ); INSERT INTO dbo.Product VALUES ( 'Red SantaSuit', 199.99 ), ( 'Candy Canes', 1.99 ), ( 'Fake Snow', 2.99 ), ( 'Red Bells', 49.99 ), ( 'LED Lights', 6.99 ); CREATE TABLE dbo.SearchString ( ID INT IDENTITY , String VARCHAR(100) ); INSERT INTO dbo.SearchString VALUES ( 'Red' ), ( 'Lights' ), ( 'Star' ); GO CREATE FUNCTION dbo.FindProductLike ( @FindStringVARCHAR(100) ) RETURNS TABLE AS RETURN ( SELECT ProductName, Price FROM dbo.Product WHERE ProductNameLIKE '%' + @FindString + '%' )
上面的脚本中创建了一个叫做Product的表,包含了5个不同的产品。同时也创建了一个叫做SearchString的表,包含了3个不同的字符串。最后创建一个叫做FindProductLike的表值函数。该函数接收一个@FindString参数,并在Product表中找出所有包含@FindString的ProductName。
使用CROSS APPLY 运算符:
CROSS APPLY会对相关联的每一行都应用该函数
USE tempdb; GO SELECT * FROM dbo.SearchString AS S CROSS APPLYdbo.FindProductLike(S.String);
结果如下:
回看代码可以看到,代码中使用CROSSAPPLY关联SearchString表中的结果集和FindProductLike表值函数。CROSS APPLY从SearchString中获取String值,然后调用函数FindProductLike。如果函数返回数据,则与SearchString的行关联。
前两行的数据来自于字符串“Red”,当“Red”传输给函数后,返回包含该值的ProductName和Price,然后和SearchString关联,把包含“Red”值的产品返回到结果集中。第三行数据和前两行的产生原理一致,但是是由“Lights”产生。字符串“Star”由于没有在Product中得到匹配值,所以不返回结果。
使用OUTER APPLY 运算符:
该操作符和CROSS APPLY的唯一区别是返回所有数据,包括没有匹配的值:
USE tempdb; GO SELECT * FROM dbo.SearchString AS S OUTER APPLYdbo.FindProductLike(S.String);
从结果中可以看出,对于字符串“Star”,OUTER APPLY也返回结果,只是返回NULL。
使用表值表达式:
下面演示一下使用表值表达式与APPLY的操作。
USE tempdb; GO SELECT * FROM dbo.SearchString as S CROSS APPLY (SELECT ProductName, Price FROM dbo.Product WHERE ProductName like '%' + S.String + '%') as X
从结果上来看,和CROSS APPLY无异,仅仅是把表值函数换成了表值表达式。
总结:
APPLY运算可以把数据集中的数据与表值函数或表值表达式关联,使用APPLY可以针对表值函数或表达式的数据集进行基于集合的查询。在这种情况下可以考虑使用APPLY运算符。
---------------------------------------------------------------------翻译结束-----------------------------------------------------------------------
---------------------------------------------------------------------个人总结-----------------------------------------------------------------------
针对这个题目,我个人想法不多,因为已经很多很多年没真正做开发了。但是它给我提供了一个思路,在允许的情况下,使用新版本带来的新技术并不是意见坏事。同样是70-461上的例子,其中一个使用了窗口函数的写法,比旧写法速度快了几十倍。的确震撼了我。也坚定了使用新技术的决心。
在不久的将来,我打算升级公司物流系统的数据库版本,其中可以考虑使用的技术有:
1. 列存储索引(提高静态数据的查询效率)
2. T-SQL新语法,如OFFSET(用于分页)等。
3. AlwaysOn,用于读写分离和容灾。
4. 可能使用2014的In-Memory技术。
5. 其他待定。
我对本文的感悟就是:不要固步自封,多学习新技术,特别是和你现有技术完全不同的领域,如现在你学的是关系数据库,简称OldSQL,那么不妨学学NoSQL甚至NewSQL。
T-SQL中的APPLY用法(半翻译)的更多相关文章
-
SQL中distinct的用法
SQL中distinct的用法 1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...
-
sql中binary_checksum(*)的用法
sql中binary_checksum(*)的用法(转) binary_checksum(*)可以用来检查修改过的行. 同一行在update后,该行的binary_checksum(*)就不同. 如 ...
-
SQL中Merge的用法
SQL中Merge的用法 Merge的用法 Merge可以完成以下功能: 1. 两个表之间数据的更新 2. 进行进销存更新库存 3. 进行表之间数据的复制 语法说明: 1. 在语句结束后一定要 ...
-
SQL中Truncate的用法(转)
转自:http://www.studyofnet.com/news/555.html 本文导读:删除表中的数据的方法有delete,truncate, 其中TRUNCATE TABLE用于删除表中的所 ...
-
sql中 decode() 的用法
sql中 decode() 的用法 SELECT ID,DECODE(inParam,'Param','value1' ,'value2') name FROM yytj2018 如果 inParam ...
-
十、SQL中EXISTS的用法 十三、sql server not exists
十.SQL中EXISTS的用法 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False EXISTS 指定一个子查询,检测 行 的存在. 语法 ...
-
SQL中Truncate的用法
SQL中Truncate的用法转自:http://www.studyofnet.com/news/555.html本文导读:删除表中的数据的方法有delete,truncate, 其中TRUNCATE ...
-
SQL中CONVERT()函数用法详解
SQL中CONVERT函数格式: CONVERT(data_type,expression[,style]) 参数说明: expression 是任何有效的 Microsoft® SQL Server ...
-
SQL中CASE 的用法 转载
sql语言中有没有类似C语言中的switch case的语句?? 没有,用case when 来代替就行了. 例如,下面的语句显示中文年月 select getdat ...
随机推荐
-
mount报错: you must specify the filesystem type
在linux mount /dev/vdb 到 /home 分区时报错: # mount /dev/vdb /homemount: you must specify the filesystem ty ...
-
delphi XE4 隐藏程序在任务管理器和隐藏任务栏
最新处理方法,偶然发现delphi下有个ShowMainForm属性,只要在Application.Initialize;后面加上Application.ShowMainForm := false;就 ...
-
Zookeeper C API 指南四(C API 概览)(转)
上一节<Zookeeper C API 指南三(回调函数)>重点讲了 Zookeeper C API 中各种回调函数的原型,本节将切入正题,正式讲解 Zookeeper C API.相信大 ...
-
android学习笔记---63-PopupWindow,泡泡窗口的实现
转载http://blog.csdn.net/lidew521/article/details/8976627 PopupWindow是一个可以显示在当前Activity之上的浮动容器,PopupWi ...
-
图论 Warshall 和Floyd 矩阵传递闭包
首先我们先说下图论,一般图存储可以使用邻接矩阵,或邻接表,一般使用邻接矩阵在稠密图比较省空间. 我们来说下有向图,一般的有向图也是图,图可以分为稠密图,稀疏图,那么从意思上,稠密图就是点的边比较多,稀 ...
-
java中的单例模式与静态类
单例模式与静态类(一个类,所有方法为静态方法)是另一个非常有趣的问题,在<Java中有关单例模式的面试问题>博文中露掉了,由于单例模式和静态类都具有良好的访问性,它们之间有许多相似之处,例 ...
-
Unity3D 代码入口
最近有人提出一个unity一键导出html项目的设想,所以又回头看了一下unity 发现现在的untiy和我熟悉的有很大的不同了 在看unity的 entity 系统时,注意到,这个系统的入口比较特殊 ...
-
SQL语句利用日志写shell
outfile被禁止,或者写入文件被拦截: 在数据库中操作如下:(必须是root权限) show variables like '%general%'; #查看配置 set global genera ...
-
tf.nn.in_top_k原理探究
import tensorflow as tf; A = [[0.8,0.6,0.3], [0.1,0.6,0.4],[0.5,0.1,0.9]] B = [0,2,1] out = tf.nn.in ...
-
Docker的一些概念
Docker的一些概念 2.1 什么是Docker? 说实话关于Docker是什么并太好说,下面我通过四点向你说明Docker到底是个什么东西. Docker 是世界领先的软件容器平台. Docker ...