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)

Msg 4104, Level 16, State 1, Line 1
The multi-part identifier "T1.column_a" could not be bound.
最后的这个查询的语法有错误。在 cross join 时,表值函数的参数不能是表 T1 的字段, 为啥不能这样做呢?我猜可能微软当时没有加这个功能:),后来有客户抱怨后, 于是微软就增加了 crossapply 和 outer apply 来完善,请看 cross apply, outer apply 的例子:

-- 4. cross apply
select *
  from TABLE_1 T1
cross apply FN_TableValue(T1.column_a)

-- 5. outer apply
select *
  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 和 outerapply 的不同之处:

-- cross apply
select *
  from Departments as D
cross apply fn_getsubtree(D.deptmgrid) as ST
deptid      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 apply
select *
  from Departments as D
outer apply fn_getsubtree(D.deptmgrid) as ST
deptid      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, 0
    FROM employees
    WHERE empid = @empid   
    UNION ALL
    -- Recursive Member (RM)
    SELECT e.empid, e.empname, e.mgrid, es.lvl+1
    FROM employees AS e
       join employees_subtree AS es
          ON e.mgrid = es.empid
  )
    SELECT * FROM Employees_Subtree
)
GO

-- cross apply query
SELECT *
FROM Departments AS D
    CROSS APPLY fn_getsubtree(D.deptmgrid) AS ST

-- outer apply query
SELECT *
FROM Departments AS D
    OUTER APPLY fn_getsubtree(D.deptmgrid) AS ST

CROSS APPLY和 OUTER APPLY 区别详解的更多相关文章

  1. left ,right ,cross ,full/left outer join/区别 详解

    --创建测试表wwif OBJECT_ID('qq') is not null drop table qqcreate table qq([序号] varchar(5),[内容1] varchar(1 ...

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

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

  3. SQLServer连接查询之Cross Apply和Outer Apply的区别及用法

    https://blog.csdn.net/wikey_zhang/article/details/77480118 先简单了解下cross apply的语法以及会产生什么样的结果集吧! 示例表: S ...

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

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

  5. SQL 关于apply的两种形式cross apply 和 outer apply(转)

    转载链接:http://www.cnblogs.com/shuangnet/archive/2013/04/02/2995798.html apply有两种形式: cross apply 和 oute ...

  6. SQLServer count函数、cross apply和outer apply、

    1.COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入)2.COUNT(*) 函数返回表中的记录数 select *   from TABLE_1 T1 outer ap ...

  7. SQL 关于apply的两种形式cross apply 和 outer apply

    SQL 关于apply的两种形式cross apply 和 outer apply 例子: CREATE TABLE [dbo].[Customers]( ) COLLATE Chinese_PRC_ ...

  8. SQL关于apply的两种形式cross apply和outer apply(转载)

    SQL 关于apply的两种形式cross apply 和 outer apply   apply有两种形式: cross apply 和 outer apply   先看看语法:   <lef ...

  9. SqlSever 使用 CROSS APPLY 与 OUTER APPLY 连接查询

    前言 日常开发中遇到多表查询时,首先会想到 INNER JOIN 或 LEFT OUTER JOIN 等等,但是这两种查询有时候不能满足需求.比如,左表一条关联右表多条记录时,我需要控制右表的某一条或 ...

随机推荐

  1. Angular03 将数据添加到组件中

    准备:已经搭建好angular-cli环境.知道如何创建组件 一.将一个数据添加到组件中 1 创建一个新的组件 user-item 2 将组件添加到静态模板中 3 为组件添加属性,并利用构造器赋值 4 ...

  2. iOS 添加Empty Application模板

    在Apple最新的XCode6.x中没有了Empty Application模板,好在XCode可以添加模板,而且可以自定义模板. 首先可以到XCode5.x中复制 Empty Application ...

  3. vue 之 介绍及简单使用

    浏览目录 vue的介绍 vue的使用 vue的介绍 简介 vue官网说:Vue.js(读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue 采用自底 ...

  4. 37LCD-TFTLCD原理与配置

    1.TFTLCD驱动原理 简介

  5. Umbraco中如何找到home node

    在一个Umbraco项目中,我们经常会出现需要找到这个项目的home node的情况, 那么如何来找到项目的home node呢 方法如下: 1. 在View中 @inherits Umbraco.W ...

  6. ISE 14.7 XST.exe stop working

    http://www.xilinx.com/support/answers/59851.html Description XST completes but then instead of retur ...

  7. [学习笔记]父进程wait和waitpid

    1.wait和waitpid出现的原因 SIGCHLD q  当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) q  子进程退 ...

  8. win7 64位 [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认

    问题描述: VBA程序连接Access数据库,Excel中执行相关宏,提示[Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认 解决方案: 1.重新安装 AccessDa ...

  9. C#中virtual和abstract区别,举例子

    virtual和abstract都是用来修饰父类的,通过覆盖父类的定义,让子类重新定义. 它们有一个共同点:如果用来修饰方法,前面必须添加public,要不然就会出现编译错误:虚拟方法或抽象方法是不能 ...

  10. ecto使用