`
hypgr
  • 浏览: 276902 次
社区版块
存档分类
最新评论

SQL Server 2005 中 Cross Apply & Outer Apply

阅读更多

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 的字段, 为啥不能这样做呢?我猜可能微软当时没有加这个功能:),后来有客户抱怨后, 于是微软就增加了 cross apply 和 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 和 outer apply 的不同之处:

-- 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
create table Employees
(
  empid   int         not null,
  mgrid   int         NULL,
  empname varchar(25) not null,
  salary  money       not null
)
go


-- create Departments table and insert values
create table Departments
(
  deptid    int not null primary key,
  deptname  varchar(25) not null
)
go

-- fill datas
insert into employees values(1 , NULL, 'Nancy'   , 000.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


-- table-value function
create function dbo.fn_getsubtree(@empid AS INT) returns @TREE table
(
  empid   int not null,
  empname varchar(25) not null,
  mgrid   int null,
  lvl     int not null
)
as
begin
  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
  )


  insert into @TREE
    select * from Employees_Subtree

  return
end
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
分享到:
评论

相关推荐

    SQL Server CROSS APPLY和OUTER APPLY的应用详解

    SQL Server中的CROSS APPLY和OUTER APPLY是两种特殊的表运算符,它们在2005版本及以上引入,主要用于处理复杂的数据转换和联接操作。这些运算符的主要区别在于如何处理右表表达式的结果。 CROSS APPLY用于执行内联...

    sql server关键字详解大全(图文)

    下面把sqlserver中cross apply和outer apply关键字具体介绍展示如下: 1.CROSS APPLY 和OUTER APPLY MSDN解释如下(个人理解不是很清晰): 使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值...

    SQL Server 2005 T-SQL增强_PDF

    《SQL Server 2005 T-SQL增强》是一本专为SQL Server 2005用户准备的技术指南,深入探讨了T-SQL(Transact-SQL)在该版本中的新特性和强化功能。T-SQL是SQL Server的核心查询语言,用于数据查询、更新、插入和删除等...

    解析SQL Server 2005溢用之:合并列值

    在SQL Server 2005中,有了新的解决方案,我们可以利用`FOR XML PATH`结合`CROSS APPLY`或`OUTER APPLY`来达到相同的目的,但这种方法更加高效且直观。以下是一个例子: ```sql DECLARE @t TABLE(id int, value ...

    SQLServer APPLY表运算符使用介绍

    SQL Server的APPLY表运算符是在SQL Server 2005及更高版本中引入的一个强大工具,它为复杂的查询提供了更多的灵活性。APPLY运算符分为两种类型:CROSS APPLY和OUTER APPLY,它们在处理数据时有显著的区别。 CROSS ...

    #507 SQL Server 2005 T-SQL Enhancements

    本文由Itzik Ben-Gan和Solid Quality Learning发布,旨在介绍SQL Server 2005中的一些主要T-SQL新特性。以下是这些增强功能的详细说明: 1. **窗口函数(Window Functions)**:SQL Server 2005引入了窗口函数,如...

    SQLServer 2008 R2中使用Cross apply统计最新数据和最近数据

    总的来说,`APPLY`运算符,特别是`CROSS APPLY`,在SQL Server 2008 R2中是一个强大的工具,可用于处理复杂的查询需求,如统计和聚合数据。结合窗口函数,它可以有效地解决特定的统计问题,如找出每个组的最新和次新...

    sql server 2008中的apply运算符使用方法

    在SQL Server 2008中,`APPLY`运算符是一种高级联接操作,它允许将一个查询的结果集作为另一个查询的输入,从而实现复杂的数据处理。`APPLY`运算符分为两种类型:`CROSS APPLY`和`OUTER APPLY`,它们都是在查询中...

    sql server 性能优化(生产中常用)

    窗口函数是SQL Server中非常强大的功能,它允许开发者在查询中进行更复杂的数据聚合操作。窗口函数特别适用于执行计算、排名和分组数据,其处理效率远高于传统的聚合函数。 28. OUTER APPLY、CROSS APPLY区别 OUTER...

    SQL2005 PPT 下载

    - **CROSS APPLY和OUTER APPLY**:扩展了JOIN操作,允许在JOIN过程中调用用户定义的函数或子查询。 3. **安全性与权限管理** - **角色管理**:强化了角色管理,允许更精细的权限分配,例如服务器级别的角色和...

    SQL Server和Oracle的常用函数对比.rar

    - 两个系统都支持`JOIN`操作,如`INNER JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `FULL JOIN`,但SQL Server的`CROSS APPLY`和`OUTER APPLY`提供了更灵活的连接方式,Oracle则没有直接对应的特性。 9. **游标**: - ...

    SQLServer中文帮助《从入门到精通》还有代码讲解.chm.rar

    7. **高级查询技巧**:使用PIVOT和UNPIVOT进行数据旋转,使用CROSS APPLY和OUTER APPLY进行复杂数据转换。 通过这两个CHM文件,学习者可以系统地了解和掌握SQL Server的基础知识和查询技能,结合实际代码讲解,将...

    SQL2005学习笔记 APPLY 运算符

    在SQL Server 2005中,`APPLY`运算符是一个重要的查询增强功能,它允许更灵活地在查询中使用表值函数。本篇学习笔记将深入探讨`APPLY`运算符的基本概念、用途以及与传统JOIN操作的对比。 `APPLY`运算符分为两种类型...

    SQL Server Useful DMVs

    这个查询可以帮助我们了解 SQL Server 缓存中的执行计划,包括 SQL 语句文本、计划类型、数据库名称以及计划使用的次数等。 ##### 2. 最昂贵的查询 ```sql SELECT CAST(Total_elapsed_time / 1000000.0 AS DECIMAL...

    SQL2005ppt电子课件

    2. **Transact-SQL增强**:SQL2005扩展了T-SQL语言,添加了窗口函数、CROSS APPLY和OUTER APPLY等新功能,使得复杂查询和数据分析更为便捷。 3. **企业管理器**:SQL Server Management Studio (SSMS) 是SQL2005的...

    sqlserver函数大全.pdf

    **行集函数**,如CROSS APPLY和OUTER APPLY,允许在查询中生成新的行集,通常与子查询或表值函数一起使用。 **安全函数**,与权限和角色管理相关,如IS_MEMBER()检查用户是否属于特定的角色。 **字符串函数**,如...

Global site tag (gtag.js) - Google Analytics