SQL Server 2005 新增 cross apply 和 outer apply 联接语句,增加这两个东东有啥作用呢?

我们知道有个 SQL Server 2000 中有个 cross join 是用于交叉联接的。实际上增加 cross apply 和 outer apply 是用于交叉联接表值函数(返回表结果集的函数)的, 更重要的是这个函数的参数是另一个表中的字段。这个解释可能有些含混不请,请看下面的例子:

-- 1. cross join 联接两个表
select *  from TABLE_1 as T1
cross join TABLE_2 as T2【此句实际上是求笛卡尔积】
-- 2. cross join 联接表和表值函数,表值函数的参数是个“常量”select *from TABLE_1 T1
cross join FN_TableValue(100)-- 3. cross join  联接表和表值函数,表值函数的参数是“表T1中的字段”select *from TABLE_1 T1
cross join FN_TableValue(T1.column_a)Error:Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "T1.column_a" could not be bound.最后的这个查询的语法有错误。在 cross join 时,表值函数的参数不能是表 T1 的字段, 为啥不能这样做呢?我猜可能微软当时没有加这个功能:),后来有客户抱怨后, 于是微软就增加了 cross apply 和 outer apply 来完善,请看 cross apply, outer apply 的例子: -- 4. cross applyselect *from TABLE_1 T1
cross apply FN_TableValue(T1.column_a)-- 5. outer applyselect *from TABLE_1 T1
outer apply FN_TableValue(T1.column_a)cross apply 和 outer apply 对于 T1 中的每一行都和派生表(表值函数根据T1当前行数据生成的动态结果集) 做了一个交叉联接。cross apply 和outer apply 的区别在于: 如果根据 T1 的某行数据生成的派生表为空,cross apply 后的结果集 就不包含 T1 中的这行数据,而 outer apply 仍会包含这行数据,并且派生表的所有字段值都为 NULL。 下面的例子摘自微软 SQL Server 2005 联机帮助,它很清楚的展现了 cross apply 和 outer apply 的不同之处: -- cross applyselect *from Departments as D
cross apply fn_getsubtree(D.deptmgrid) as STdeptid      deptname      deptmgrid   empid       empname       mgrid       lvl
----------- -----------   ----------- ----------- -----------   ----------- ------
1           HR            2           2           Andrew        1           0
1           HR            2           5           Steven        2           1
1           HR            2           6           Michael       2           1
2           Marketing     7           7           Robert        3           0
2           Marketing     7           11          David         7           1
2           Marketing     7           12          Ron           7           1
2           Marketing     7           13          Dan           7           1
2           Marketing     7           14          James         11          2
3           Finance       8           8           Laura         3           0
4           R&D           9           9           Ann           3           0
5           Training      4           4           Margaret      1           0
5           Training      4           10          Ina           4           1(12 row(s) affected)-- outer applyselect *from Departments as D
outer apply fn_getsubtree(D.deptmgrid) as STdeptid      deptname      deptmgrid   empid       empname       mgrid       lvl
----------- -----------   ----------- ----------- -----------   ----------- ------
1           HR            2           2           Andrew        1           0
1           HR            2           5           Steven        2           1
1           HR            2           6           Michael       2           1
2           Marketing     7           7           Robert        3           0
2           Marketing     7           11          David         7           1
2           Marketing     7           12          Ron           7           1
2           Marketing     7           13          Dan           7           1
2           Marketing     7           14          James         11          2
3           Finance       8           8           Laura         3           0
4           R&D           9           9           Ann           3           0
5           Training      4           4           Margaret      1           0
5           Training      4           10          Ina           4           1
6           Gardening     NULL        NULL        NULL          NULL        NULL(13 row(s) affected)注意 outer apply 结果集中多出的最后一行。 当 Departments 的最后一行在进行交叉联接时:deptmgrid 为 NULL,fn_getsubtree(D.deptmgrid) 生成的派生表中没有数据,但 outer apply 仍会包含这一行数据,这就是它和 cross join 的不同之处。 下面是完整的测试代码,你可以在 SQL Server 2005 联机帮助上找到: -- create Employees table and insert values
IF OBJECT_ID('Employees') IS NOT NULL
DROP TABLE Employees
GO
CREATE TABLE Employees
(
empid INT NOT NULL,
mgrid INT NULL,
empname VARCHAR(25) NOT NULL,
salary MONEY NOT NULL
)
GO
IF OBJECT_ID('Departments') IS NOT NULL
DROP TABLE Departments
GO
-- create Departments table and insert values
CREATE TABLE Departments
(
deptid INT NOT NULL PRIMARY KEY,
deptname VARCHAR(25) NOT NULL,
deptmgrid INT
)
GO-- fill datas
INSERT  INTO employees VALUES  (1,NULL,'Nancy',00.00)
INSERT  INTO employees VALUES  (2,1,'Andrew',00.00)
INSERT  INTO employees VALUES  (3,1,'Janet',00.00)
INSERT  INTO employees VALUES  (4,1,'Margaret',00.00)
INSERT  INTO employees VALUES  (5,2,'Steven',00.00)
INSERT  INTO employees VALUES  (6,2,'Michael',00.00)
INSERT  INTO employees VALUES  (7,3,'Robert',00.00)
INSERT  INTO employees VALUES  (8,3,'Laura',00.00)
INSERT  INTO employees VALUES  (9,3,'Ann',00.00)
INSERT  INTO employees VALUES  (10,4,'Ina',00.00)
INSERT  INTO employees VALUES  (11,7,'David',00.00)
INSERT  INTO employees VALUES  (12,7,'Ron',00.00)
INSERT  INTO employees VALUES  (13,7,'Dan',00.00)
INSERT  INTO employees VALUES  (14,11,'James',00.00)INSERT  INTO departments VALUES  (1,'HR',2)
INSERT  INTO departments VALUES  (2,'Marketing',7)
INSERT  INTO departments VALUES  (3,'Finance',8)
INSERT  INTO departments VALUES  (4,'R&D',9)
INSERT  INTO departments VALUES  (5,'Training',4)
INSERT  INTO departments VALUES  (6,'Gardening',NULL)
GO
--SELECT * FROM departments-- table-value function
IF OBJECT_ID('fn_getsubtree') IS NOT NULL
DROP FUNCTION  fn_getsubtree
GO
CREATE  FUNCTION dbo.fn_getsubtree(@empid AS INT)
RETURNS TABLE
AS
RETURN(WITH Employees_Subtree(empid, empname, mgrid, lvl)AS(-- Anchor Member (AM)SELECT empid, empname, mgrid, 0FROM employeesWHERE empid = @empid   UNION ALL-- Recursive Member (RM)SELECT e.empid, e.empname, e.mgrid, es.lvl+1FROM employees AS ejoin employees_subtree AS esON e.mgrid = es.empid)SELECT * FROM Employees_Subtree
)
GO-- cross apply query
SELECT  *
FROM Departments AS DCROSS APPLY fn_getsubtree(D.deptmgrid) AS ST-- outer apply query
SELECT  *
FROM Departments AS DOUTER APPLY fn_getsubtree(D.deptmgrid) AS ST-------------------中国风整理的两个小例子-------------------------------
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)--drop table #t,#T2
goselect*
from#T a
cross apply(select 课程,分数 from #t2 where 姓名=a.姓名) b/*
姓名         课程         分数
---------- ---------- -----------
张三         语文         74
张三         数学         83
张三         物理         93(3 行受影响)*/
select*
from#T a
outer apply(select 课程,分数 from #t2 where 姓名=a.姓名) b
/*
姓名         课程         分数
---------- ---------- -----------
张三         语文         74
张三         数学         83
张三         物理         93
李四         NULL       NULL
NULL       NULL       NULL(5 行受影响)
*/

转载于:https://www.cnblogs.com/tianyuanmuge/p/9925485.html

T-SQL Apply的用法相关推荐

  1. 9.mybatis动态SQL标签的用法

    mybatis动态SQL标签的用法 动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦 ...

  2. PL/SQL 的一些用法

    变量的声明,赋值,打印(declare是pl/sql里面的用法 variable是sql*plus里面的用法,variable相当于一个sql*plus环境的全局变量,declare里定义的是pl/s ...

  3. SQL CASE WHEN用法

    SQL CASE WHEN用法 CASE 可能是 SQL 中被误用最多的关键字之一.虽然你可能以前用过这个关键字来创建字段,但是它还具有更多用法.例如,你可以在 WHERE 子句中使用 CASE . ...

  4. sql not exists用法_SQL Server 2012 高级用法(一)

    最近用到了SQL Server 相关数据库等问题,于是整理了如下SQL Server高级用法系列. 该系列不再介绍基础用法(select ,insert, update, delete, and or ...

  5. PL/SQL之JOB用法 (定时跑数据)

    转载自   PL/SQL之JOB用法 (定时跑数据) 一.DBMS_Job包的用法   包含以下子过程:        Broken()过程.      change()过程.      Interv ...

  6. COLLATE oracle,Sql 中Collate用法

    今天查询sqlite的时候需要不区分大小写,查了下文档,需要使用collate nocase.顺便学习下collate的用法. collate在sql中是用来定义排序规则的.排序规则其实就是当比较两个 ...

  7. sql replace函数用法_esProc 的 SQL 应用方案

    esProc 的 SQL 功能支持文件计算.性能优化等独特功能,本文将总结桌面 IDE.命令行等不同环境下 SQL 的用法,以及常用文件格式.特殊分隔符等多种应用方案,详情点击esProc 的 SQL ...

  8. oracle数据库中sql%notfound的用法

    SQL%NOTFOUND 是一个布尔值.与最近的sql语句(update,insert,delete,select)发生交互,当最近的一条sql语句没有涉及任何行的时候,则返回true.否则返回fal ...

  9. gispython定义查询_Python与开源GIS:SpatiaLite 中的基本SQL数据库查询用法

    Python与开源GIS教程的内容,开发了单独的内容,请打开 https://www.osgeo.cn/pygis/ 查看. 本页面的内容不再更新. 这一节我们来看一下基本的SQL语句用法.使用最通用 ...

  10. sql中变量用法_SQL变量:基础和用法

    sql中变量用法 In this article, we will learn the notions and usage details of the SQL variable. In SQL Se ...

最新文章

  1. 王者荣耀服务器维护5月22,5月22日王者荣耀更新内容一览
  2. 给Source Insight做个外挂系列之三--构建外挂软件的定制代码框架
  3. java abort_Java中“...”的使用
  4. python中为什么不支持char_python支持char吗
  5. group by两个条件
  6. 2019.01.24 NOIP训练 旅行(轮廓线dp)
  7. Python提取Word文档中所有超链接地址和文本
  8. java 项目拆分_java – 多模块项目什么时候应该拆分成单独的存储库树?
  9. Ubuntu18突然卡死解决方法
  10. PHP最常用的2种设计模式工厂模式和单例模式
  11. 联想开机壁纸存放位置
  12. 计算机系挣钱的职业,十大挣钱职业之IT行业
  13. 明源售楼系统技术解析—MVC架构
  14. ios 振动棒软件_iOS 14很棒
  15. 产品经理入门——必备技能之【产品运营】
  16. Windows10ISO 22h2-19045.2006原版系统镜像2022年9月份版
  17. python 图片处理模块_(python)图片处理Pillow模块的使用
  18. mysql where 条件取反_MySQL搜索: WHERE 多条件
  19. python interpreter 中没有torch_python自动化办公之 Python 解析 PDF
  20. python读二进制格点雷达基数据_radar: 基于python pycinrad 以及多种类库 编写基于java 的雷达基数据统一格式读取...

热门文章

  1. 【数据结构和算法笔记】用c和c++分别实现二叉搜索树
  2. 开源视频会议系统:OpenMeetings 安装方法
  3. getopt与getopt_long
  4. linux atom编码设置,Ubuntu中Atom编辑器显示中文乱码的处理方法
  5. jqGrid数据列表和表单的列隐藏/显示
  6. Oracle 中data与timstamp互转
  7. echarts柱状图的数据差距过大影响美观
  8. 工具箱锁打不开了怎么办_锁芯坏了门打不开怎么办?锁芯拆开的方法是什么?...
  9. 2022牛客寒假算法基础集训营6 签到题5题(附基础集训营4-6签到题总结)
  10. 【CCCC】L3-025 那就别担心了 (30分),dfs搜索起点到终点的路径条数。