SQL Server 2005参考:Apply运算符
使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。
APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。
APPLY 有两种形式: CROSS APPLY 和 OUTER APPLY。CROSS APPLY 仅返回外部表中通过表值函数生成结果集的行。OUTER APPLY 既返回生成结果集的行,也返回不生成结果集的行,其中表值函数生成的列中的值为 NULL。
--Create table Employees table and insert Values
CREATE TABLE Employees
(
emp_id INT NOT NULL,
mgr_id INT NULL,
emp_name VARCHAR(20) NOT NULL,
emp_salary MONEY NOT NULL,
CONSTRAINT pk_id PRIMARY KEY(emp_id)
)
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)
CREATE TABLE Departments
(
dep_id INT NOT NULL,
dep_name VARCHAR(30) NOT NULL,
dep_m_id INT NULL REFERENCES Employees(emp_id)
)
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(即dep_m_id)也是来自与Employees 表中的雇员(即与某一dep_id对应)。
-- 下面的表值函数使用雇员ID 作为参数,并返回该雇员及其所有下属
CREATE FUNCTION fn_getSubTree
(
@emp_id INT
)
RETURNS @tree TABLE
(
emp_id INT NOT NULL,
emp_name VARCHAR(20) NOT NULL,
mgr_id INT NULL,
lvl INT NOT NULL
)
AS
BEGIN
WITH emp_subtree(emp_id,emp_name,mgr_id,lvl)
AS
(
SELECT emp_id,emp_name,mgr_id,0 FROM Employees WHERE emp_id=@emp_id
UNION ALL
SELECT e.emp_id,e.emp_name,e.mgr_id,es.lvl+1
FROM Employees e JOIN emp_subtree es ON e.mgr_id=es.emp_id
)
INSERT INTO @tree
SELECT * FROM emp_subtree
RETURN
END
-- 返回每个部门经理的所有级别的全部下属
SELECT * FROM Departments AS D CROSS APPLY fn_getsubtree(D.dep_m_id) AS ST
-- 园艺部门不会显示在结果中。因为此部门没有经理,fn_getsubtree 为其返回了一个空集.
-- 使用OUTER APPLY,园艺部门也会显示在结果集中,其中deptmgrid 字段中的值以及fn_getsubtree 返回的字段中的值均为NULL.
SELECT * FROM Departments AS D OUTER APPLY fn_getsubtree(D.dep_m_id) AS ST