简单来说,apply可以理解为join 但是,join时,右端输入如果是子查询是不可能引用左端内容的。apply就对此做了突破。并且把连接条件放到了子查询里面。具体官话怎么说,咱也不清楚,就是这么理解的。select * from ta a inner join tb b on a.id=b.idselect * from ta a cross apply (select * from tb where id=a.id) b 再注意一点:当右端输入的行集依赖于或者说跟具左端行的值来确定的话,join是很难做到的。而apply就做了语法突破。 即,右端行集本身的产生可以引用左端输入, 而join是不支持的,要自己写语句转换。有些情况下,join是做不到的。
使用 APPLY 发送反馈
请参阅
全部折叠全部展开 语言筛选器: 全部语言筛选器: 多语言语言筛选器: Visual Basic语言筛选器: C#语言筛选器: C++语言筛选器: J#语言筛选器: JScript
访问和更改数据库数据 > 查询基础知识 > 使用 FROM 子句 >
Visual Basic(Declaration)
C#
C++
J#
JScript使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。 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 *
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 返回给部门经理的行数一样多。 此外,园艺部门不会显示在结果中。因为此部门没有经理,fn_getsubtree 为其返回了一个空集。使用 OUTER APPLY,园艺部门也会显示在结果集中,其中 deptmgrid 字段中的值以及 fn_getsubtree 返回的字段中的值均为 NULL。请参阅
其他资源
FROM (Transact-SQL)
帮助和信息
获取 SQL Server 2005 帮助文档反馈
Microsoft 非常重视您的反馈。若要对该主题分级并将对该主题的反馈发送到文档编写组,请单击一个分级,再单击“发送反馈”。要想获得有关支持方面的问题的协助,请参阅包含在该产品中的技术支持信息。
不好 1
2
3
4
5
出色
若要将反馈通过电子邮件发送给 Microsoft,请单击此处:
(C) 2005 Microsoft Corporation。保留所有权利。
引用關係時,這里有用到;具體注意用時多測
http://topic.csdn.net/u/20080612/22/c850499f-bce3-4877-82d5-af2357857872.html
使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。
但是,join时,右端输入如果是子查询是不可能引用左端内容的。apply就对此做了突破。并且把连接条件放到了子查询里面。具体官话怎么说,咱也不清楚,就是这么理解的。select * from ta a inner join tb b on a.id=b.idselect * from ta a
cross apply (select * from tb where id=a.id) b
再注意一点:当右端输入的行集依赖于或者说跟具左端行的值来确定的话,join是很难做到的。而apply就做了语法突破。
即,右端行集本身的产生可以引用左端输入, 而join是不支持的,要自己写语句转换。有些情况下,join是做不到的。