原文地址:http://technet.microsoft.com/zh-cn/library/ms175156(v=SQL.105).aspx

使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。

注意

若要使用 APPLY,数据库兼容级别必须至少为 90。

APPLY 有两种形式:CROSS APPLY 和 OUTER APPLY。CROSS APPLY 仅返回外部表中通过表值函数生成结果集的行。OUTER APPLY 既返回生成结果集的行,也返回不生成结果集的行,其中表值函数生成的列中的值为 NULL。

例如,考虑下列表 Employees 和 Departments:

 
复制
--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
CONSTRAINT PK_Employees PRIMARY KEY(empid)
);
GO
INSERT INTO Employees VALUES(1 , NULL, 'Nancy' , $10000.00);
INSERT INTO Employees VALUES(2 , 1 , 'Andrew' , $5000.00);
INSERT INTO Employees VALUES(3 , 1 , 'Janet' , $5000.00);
INSERT INTO Employees VALUES(4 , 1 , 'Margaret', $5000.00);
INSERT INTO Employees VALUES(5 , 2 , 'Steven' , $2500.00);
INSERT INTO Employees VALUES(6 , 2 , 'Michael' , $2500.00);
INSERT INTO Employees VALUES(7 , 3 , 'Robert' , $2500.00);
INSERT INTO Employees VALUES(8 , 3 , 'Laura' , $2500.00);
INSERT INTO Employees VALUES(9 , 3 , 'Ann' , $2500.00);
INSERT INTO Employees VALUES(10, 4 , 'Ina' , $2500.00);
INSERT INTO Employees VALUES(11, 7 , 'David' , $2000.00);
INSERT INTO Employees VALUES(12, 7 , 'Ron' , $2000.00);
INSERT INTO Employees VALUES(13, 7 , 'Dan' , $2000.00);
INSERT INTO Employees VALUES(14, 11 , 'James' , $1500.00);
GO
--Create Departments table and insert values.
CREATE TABLE Departments
(
deptid INT NOT NULL PRIMARY KEY
,deptname VARCHAR(25) NOT NULL
,deptmgrid INT NULL REFERENCES Employees
);
GO
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);

Departments 表中的多数部门都具有一个经理 ID,这些 ID 与 Employees 表中的雇员相对应。以下表值函数接受雇员 ID 作为参数,并返回该雇员和他/她的所有下属。

 
复制
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

若要返回每个部门经理的各级下属,请使用以下查询。

 
复制
SELECT D.deptid, D.deptname, D.deptmgrid
,ST.empid, ST.empname, ST.mgrid
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

注意,Departments 表中每一行复制的次数与针对部门经理执行 fn_getsubtree 而返回的行数相同。

另外,结果中不显示 Gardening 部门。因为该部门没有经理,所以 fn_getsubtree 将针对该部门返回空集。通过使用 OUTER APPLY,Gardening 部门也将在结果集中显示,其 deptmgrid 字段以及由 fn_getsubtree 返回的字段中的值都为 Null 值。

使用 APPLY的更多相关文章

  1. JS核心系列:浅谈 call apply 与 bind

    在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...

  2. SQL Server-聚焦APPLY运算符(二十七)

    前言 其实有些新的特性在SQL Server早就已经出现过,但是若非系统的去学习数据库你会发现在实际项目中别人的SQL其实是比较复杂的,其实利用新的SQL Server语法会更加方便和简洁,从本节开始 ...

  3. 利用apply()或者rest参数来实现用数组传递函数参数

    关于call()和apply()的用法,MDN文档里写的非常清晰明白,在这里就不多做记录了. https://developer.mozilla.org/zh-CN/docs/Web/JavaScri ...

  4. 由js apply与call方法想到的js数据类型(原始类型和引用类型)

    原文地址:由js apply与call方法想到的js数据类型(原始类型和引用类型) js的call方法与apply方法的区别在于第二个参数的不同,他们都有2个参数,第一个为对象(即需要用对象a继承b, ...

  5. JavaScript学习笔记(二)——闭包、IIFE、apply、函数与对象

    一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...

  6. 瞬间记住Javascript中apply与call的区别

    关于Javascript函数的apply与call方法的用法,网上的文章很多,我就不多话了.apply和call的作用很相似,但使用方式有区别 apply与call的第一个参数都是一个对象,这个对象就 ...

  7. scope.$apply是干嘛的

    开始用angular做项目的时候,一定碰到过$scope.$apply()方法,表面上看,这像是一个帮助你进行数据更新的方法,那么,它为何存在,我们又该如何使用它呢. JavaScript执行顺序 J ...

  8. JavaScript中的apply,call与this的纠缠

    1.apply定义 apply:调用函数,并用指定对象替换函数的 this 值,同时用指定数组替换函数的参数. 语法:apply([thisObj[,argArray]]) thisObj 可选.要用 ...

  9. jQuery之常用且重要方法梳理(siblings,nextAll,end,wrap,apply,call,each)-(二)

    1.siblings() siblings() 获得匹配集合中每个元素的同胞,通过选择器进行筛选是可选的. <body> <div><span>Hello</ ...

  10. JS中 call() 与apply 方法

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...

随机推荐

  1. 将Apache添加为Linux的服务 实现自启动(转)

    在Linux下用源代码方式编译安装完Apache后,启动关闭Apache可以通过如下命令实现: /app/apache2.2.14/bin/apachectl start | stop | resta ...

  2. 从零开始写一个Tomcat(贰)--建立动态服务器

    上文书说道如何通过http协议建立一个静态的服务器来访问静态网页,但我们选择tomcat最主要的原因还是因为它能动态的执行servlet,这边文章将引导你实现一个能够运行servlet的服务器,这个简 ...

  3. linux grep常用参数

    # grep [-acinv] [--color=auto] '搜寻字符串' filename选项与参数:-c :计算找到 '搜寻字符串' 的次数-i :忽略大小写的不同,所以大小写视为相同-n :顺 ...

  4. Http 辅助类

    using System; using System.Drawing; using System.IO; using System.Net; using System.Net.Cache; using ...

  5. tomcat加载不了spring-webjar终极解决办法

    Problems: I included: all Spring libs, Apache Tomcat 7.0 library in Build Path but it still gives er ...

  6. Windbg简单介绍

    1.1 使用帮助 Windbg中的命令分为三种:基本命令.元命令和扩展命令.基本命令和元命令都是调试器自带的,元命令以" ."开头. 扩展命令是外部加入的,以"!&quo ...

  7. 网页上facebook分享功能的具体实现

    1,一个链接: 参数是要分享的页面的链接 代码如下: <a style="width:35px; height:40px; position:relative; top:10px; l ...

  8. myeclipse 8.5打开文件Could not open the editor: Invalid thread access 异常

    最近打开了一个好久没用的myeclipse 8.5下的工作区间,导入一个项目,想打开文件编辑提示Could not open the editor: Invalid thread access

  9. 关于cocopads 不能正确安装的问题

    通过几个网页 我搜到 看着几个网页就够了 绝对可以实现的 http://code4app.com/article/cocoapods-install-usage http://www.cnblogs. ...

  10. javascript代码放置位置对程序的影响

    在编写html文档时,javascript可以放置的位置有两个地方<head>或者<body>,但是放置的地方,会对 JavaScript 代码的正常执行会有一定影响.由于 H ...