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

例子:

CREATE TABLE [dbo].[Customers](
[customerid] [char](5) COLLATE Chinese_PRC_CI_AS NOT NULL,
[city] [varchar](10) COLLATE Chinese_PRC_CI_AS NOT NULL,
PRIMARY KEY CLUSTERED
(
[customerid] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] insert into dbo.Customers values('FISSA','Madrid');
insert into dbo.Customers values('FRNDO','Madrid');
insert into dbo.Customers values('KRLOS','Madrid');
insert into dbo.Customers values('MRPHS','Zion'); select * from dbo.Customers CREATE TABLE [dbo].[Orders](
[orderid] [int] NOT NULL,
[customerid] [char](5) COLLATE Chinese_PRC_CI_AS NULL,
PRIMARY KEY CLUSTERED
(
[orderid] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] insert into dbo.Orders values(1,'FRNDO');
insert into dbo.Orders values(2,'FRNDO');
insert into dbo.Orders values(3,'KRLOS');
insert into dbo.Orders values(4,'KRLOS');
insert into dbo.Orders values(5,'KRLOS');
insert into dbo.Orders values(6,'MRPHS');
insert into dbo.Orders values(7,null); select * from dbo.orders --得到每个消费者最新的两个订单:
--用cross apply select *
from dbo.Customers as C
cross apply
(select top 2 *
from dbo.Orders as O
where C.customerid=O.customerid
order by orderid desc) as CA --过程分析:
--它是先得出左表【dbo.Customers】里的数据,然后把此数据一条一条的放入右表表式中,分别得出结果集,最后把结果集整合到一起就是最终的返回结果集了
--(T1的数据 像for循环一样 一条一条的进入到T2中 然后返回一个集合 最后把所有的集合整合到一块 就是最终的结果),
--最后我们再理解一下上面让记着的话(使用apply就像是先计算左输入,让后为左输入中的每一行计算一次右输入)是不是有所明白了。
--实验:用outer apply 试试看看的到的结果: select *
from dbo.Customers as C
outer apply
(select top 2 *
from dbo.Orders as O
where C.customerid=O.customerid
order by orderid desc) as CA --结果分析:
--发现outer apply得到的结果比cross多了一行,我们结合上面所写的区别(cross apply和outer apply 总是包含步骤A1,只有outer apply包含步骤A2,
--如果cross apply左行应用右表表达式时返回空积,则不返回该行。而outer apply返回改行,并且改行的右表表达式的属性为null)就会知道了。

例子:

--下面是完整的测试代码,你可以在 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 select * from employees
select * from Departments select * from fn_getsubtree(2)
select * from fn_getsubtree(3)
select * from fn_getsubtree(4)
select * from fn_getsubtree(5)
select * from fn_getsubtree(6)

例子:

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
go select
*
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 行受影响) */

SQL 关于apply的两种形式cross apply 和 outer apply的更多相关文章

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

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

  2. 转:SQL 关于apply的两种形式cross apply 和 outer apply

    原文地址:http://www.cnblogs.com/Leo_wl/archive/2013/04/02/2997012.html SQL 关于apply的两种形式cross apply 和 out ...

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

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

  4. SQL 关于apply的两种形式cross apply 和 outer apply, with cube 、with rollup 和 grouping

    1). apply有两种形式: cross apply 和 outer apply先看看语法: <left_table_expression> {cross|outer} apply &l ...

  5. C# ASP.NET(配置数据库 sql server 地址的两种形式以及配置信息的获取)

    ( 1 ) 数据库装在本机,并且采用windows认证模式 <connectionStrings>    <add name="SQLConnectionString&qu ...

  6. 在sql中case子句的两种形式

    case子句,在select后面可以进行逻辑判断. 两种形式:判断相等.判断不等 一.判断相等的语法: case 列名 when ...  then ... when ...  then ... el ...

  7. MyBatis collection的两种形式——MyBatis学习笔记之九

    与association一样,collection元素也有两种形式,现介绍如下: 一.嵌套的resultMap 实际上以前的示例使用的就是这种方法,今天介绍它的另一种写法.还是以教师映射为例,修改映射 ...

  8. 基于 Scrapy-redis 两种形式的分布式爬虫

    基于 Scrapy-redis 两种形式的分布式爬虫 .caret, .dropup > .btn > .caret { border-top-color: #000 !important ...

  9. C++:一般情况下,设计函数的形参只需要两种形式

    C++:一般情况下,设计函数的形参只需要两种形式.一,是引用形参,例如 void function (int &p_para):二,是常量引用形参,例如 void function(const ...

随机推荐

  1. vim语法高亮不起作用解决

    首先将vim更新为最新版yum -y install vim,并安装Vim的加强版vim-enhanced ,以安装支持彩色的组件    yum -y install vim-enhanced 接下来 ...

  2. libevent

    libevent doc example #include <event2/event.h> void cb_func(evutil_socket_t fd, short what, vo ...

  3. BabeLua

    http://cn.cocos2d-x.org/tutorial/show?id=507 command : -workdir E:\xg_svn\client\cocos2d-x-2.2.2\pro ...

  4. 最近读的javascript,一些文章

    本帖子是记录一些javascript的一些文章: 1. 理解node.js 2.异步编程 http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF% ...

  5. Oracle存储过程,以逗号分隔字符串传参的处理

    Oracle存储过程,经常会遇见传入的参数是逗号分隔. 处理需要3步: 第一步,创建Type类型 第二部,创建函数 第三部,创建存储过程 代码如下: 第一步: create or replace ty ...

  6. 出现Assertion failure in -[***** layoutSublayersOfLayer:]

    在自定义的view中使用了[self layoutIfNeeded]方法,在iOS8\9上都没有错误,但是在iOS7上出现了页面错乱,解决方案就是在自定义的view里面添加如下代码: + (void) ...

  7. vim中多标签和多窗口的使用

    用vim进行编辑的时候常常因为要编辑多个文件或者是编辑一个文件要参考其他文件而烦恼,这里介绍两种方法: 1.多标签 直接在编辑的时候输入: vim -p 要编辑的文件名 如vim -p * 就是编辑当 ...

  8. centos7.0 手动编译 lamp环境

    首先新建用户 lamper,并添加 sodu权限 两种方法:is not in the sudoers file 解决(转) xx is not in the sudoers file 问题解决[转载 ...

  9. 转:CWnd的函数,以后可以在这儿找了!

    CWnd CObject  └CCmdTarget     └CWnd CWnd类提供了微软基础类库中所有窗口类的基本功能.CWnd对象与Windows的窗口不同,但是两者有紧密联系.CWnd对象是由 ...

  10. Android working with Volley

    Volley是google官方推出的一个开源网络访问库,在项目中直接使用它,而不需要写一大堆的重复的代码; 项目主页: https://android.googlesource.com/platfor ...