SQL Server 2005 Hierarchies WITH Common Table Expressions

代码
  1 create table Employee
  2 (
  3 Id INT IDENTITY(1,1PRIMARY KEY
  4 [Name] varchar(30null
  5 JobTitle varchar(30null
  6 Manager int null
  7 )
  8 
  9 insert Employee
 10 select 'incf',     'IT Director',null union all
 11 select 'inc3',     'Finance Director',null union all
 12 select 'geovindu',     'assces',1 union all
 13 select 'du',     'assces',1 union all
 14 select 'fa','account',2 union all
 15 select 'd','account',2  
 16 
 17 WITH OrganisationChart (Id, [Name], JobTitle, Manager) AS
 18 (
 19       SELECT
 20             Id, [Name], JobTitle, Manager
 21       FROM dbo.Employee
 22       WHERE
 23             Manager IS NULL
 24       UNION ALL
 25       SELECT emp.Id, emp.[Name], emp.JobTitle, emp.Manager
 26       FROM dbo.Employee emp
 27       INNER JOIN OrganisationChart ON
 28             emp.Manager = OrganisationChart.Id
 29 )
 30 SELECT * FROM OrganisationChart
 31 
 32 
 33 WITH OrganisationChart (Id,  [Name], JobTitle, [Level], Manager) AS
 34 (
 35       SELECT
 36             Id, [Name], JobTitle, 0, Manager
 37       FROM  dbo.Employee
 38       WHERE
 39            Manager IS NULL
 40       UNION ALL
 41       SELECT emp.Id, emp.[Name], emp.JobTitle, [Level] + 1, emp.Manager
 42       FROM dbo.Employee emp
 43       INNER JOIN OrganisationChart ON
 44             emp.Manager = OrganisationChart.Id
 45 )
 46 SELECT * FROM OrganisationChart
 47 ORDER BY [Level]
 48 
 49 
 50 WITH OrganisationChart (Id, [Name], JobTitle, [Level], Manager, [Root]AS
 51 (
 52       SELECT  Id, [Name], JobTitle, 0, Manager, Id
 53       FROM  dbo.Employee
 54       WHERE  Manager IS NULL
 55       UNION ALL
 56       SELECT  emp.Id,emp.[Name],emp.JobTitle,[Level] + 1,emp.Manager,[Root]
 57       FROM dbo.Employee emp
 58       INNER JOIN OrganisationChart ON
 59             emp.Manager = OrganisationChart.Id
 60 )
 61 SELECT * FROM OrganisationChart
 62 --WHERE [Name] = 'incf'
 63 WHERE [Root] = 1
 64 
 65  
 66 
 67 --示例数据库
 68 
 69 /*
 70 递归查询对于同一个表父子关系的计算提供了很大的方便,这个示例使用了SQL server 2005中的递归查询,使用的表是CarParts,这个表存储了一辆汽车的所有零件以及结构,part为零件单位,subpart为子零件,Qty为数量。
 71 
 72 具体示例如下:
 73 
 74 */ 
 75 CREATE TABLE CarParts
 76 
 77 (
 78 
 79 CarID INT NOT NULL,
 80 
 81 Part VARCHAR(15),
 82 
 83 SubPart VARCHAR(15),
 84 
 85 Qty INT
 86 
 87 )
 88 
 89 GO
 90 
 91 INSERT CarParts VALUES (1'Body''Door'4)
 92 
 93 INSERT CarParts VALUES (1'Body''Trunk Lid'1)
 94 
 95 INSERT CarParts VALUES (1'Body''Car Hood'1)
 96 
 97 INSERT CarParts VALUES (1'Door''Handle'1)
 98 
 99 INSERT CarParts VALUES (1'Door''Lock'1)
100 
101 INSERT CarParts VALUES (1'Door''Window'1)
102 
103 INSERT CarParts VALUES (1'Body''Rivets'1000)
104 
105 INSERT CarParts VALUES (1'Door''Rivets'100)
106 
107 INSERT CarParts VALUES (1'Door''Mirror'1)
108 
109 INSERT CarParts VALUES (1'Mirror''small_Mirror'4)
110 
111 GO
112 
113 SELECT * FROM CarParts
114 
115 GO
116 
117 /*
118 
119 一辆汽车需要各个零件的数目
120 
121 1个Body 需要4个Door
122 
123 1个Door 需要1个Mirror
124 
125 那么
126 
127 1个body需要4个Mirror
128 
129 结构很简单吧
130 
131 */
132 
133 WITH CarPartsCTE(SubPart, Qty)
134 
135 AS
136 
137 (
138 
139 -- 固定成员 (AM):
140 
141 -- SELECT查询无需参考CarPartsCTE
142 
143 -- 递归从此处开始
144 
145 SELECT SubPart, Qty
146 
147 FROM CarParts
148 
149 WHERE Part = 'Body'
150 
151 UNION ALL
152 
153 -- 递归成员 (RM):
154 
155 -- SELECT查询参考CarPartsCTE
156 
157 -- 使用现有数据往下一层展开
158 
159 SELECT CarParts.SubPart, CarPartsCTE.Qty * CarParts.Qty
160 
161 FROM CarPartsCTE
162 
163 INNER JOIN CarParts ON CarPartsCTE.SubPart = CarParts.Part
164 
165 WHERE CarParts.CarID = 1
166 
167 )
168 
169 SELECT SubPart,Qty AS TotalNUM
170 
171 FROM CarPartsCTE
172 
173 /*
174 
175 注意看最下层的small_Mirror 位于 表最后的位置,
176 
177 由此可以看出改递归不是开始就进行递归查询而是在1层完全展开后在根据该层展开下一层不是深度优先的递归
178 
179 */
180 
181 drop table CarParts 
182 
183  
184 
185 WITH DirectReports(groupid, member, EmployeeLevel,type) AS
186 
187 (
188 
189 SELECT groupid, member, 0,type AS EmployeeLevel
190 
191 FROM groupinfo
192 
193 WHERE groupid = 'finance_company'
194 
195 UNION ALL
196 
197 SELECT e.groupid, e.member, EmployeeLevel + 1,e.type
198 
199 FROM groupinfo e
200 
201 INNER JOIN DirectReports d
202 
203 ON e.groupid = d.member
204 
205 )
206 
207 SELECT b.nickname,groupid, member, EmployeeLevel,type
208 
209 FROM DirectReports,userbasicinfo b
210 
211 where DirectReports.member=b.id
212 
213 and type = 1 
214 
215 
216 USE AdventureWorks;
217 GO
218 WITH DirReps(ManagerID, DirectReports) AS 
219 (
220     SELECT ManagerID, COUNT(*
221     FROM HumanResources.Employee AS e
222     WHERE ManagerID IS NOT NULL
223     GROUP BY ManagerID
224 )
225 SELECT ManagerID, DirectReports 
226 FROM DirReps 
227 ORDER BY ManagerID;
228 GO
229 
230 
231 WITH DirReps (Manager, DirectReports) AS 
232 (
233     SELECT ManagerID, COUNT(*AS DirectReports
234     FROM HumanResources.Employee
235     GROUP BY ManagerID
236 
237 SELECT AVG(DirectReports) AS [Average Number of Direct Reports]
238 FROM DirReps 
239 WHERE DirectReports>= 2 ;
240 GO
241 
242  
243 
244 
245 USE AdventureWorks;
246 GO
247 WITH Sales_CTE (SalesPersonID, NumberOfOrders, MaxDate)
248 AS
249 (
250     SELECT SalesPersonID, COUNT(*), MAX(OrderDate)
251     FROM Sales.SalesOrderHeader
252     GROUP BY SalesPersonID
253 )
254 SELECT E.EmployeeID, OS.NumberOfOrders, OS.MaxDate,
255     E.ManagerID, OM.NumberOfOrders, OM.MaxDate
256 FROM HumanResources.Employee AS E
257     JOIN Sales_CTE AS OS
258     ON E.EmployeeID = OS.SalesPersonID
259     LEFT OUTER JOIN Sales_CTE AS OM
260     ON E.ManagerID = OM.SalesPersonID
261 ORDER BY E.EmployeeID;
262 GO
263 
264 ---管理員下的下屬
265 USE AdventureWorks;
266 GO
267 WITH DirectReports(ManagerID, EmployeeID, EmployeeLevel) AS 
268 (
269     SELECT ManagerID, EmployeeID, 0 AS EmployeeLevel
270     FROM HumanResources.Employee
271     WHERE ManagerID IS NULL
272     UNION ALL
273     SELECT e.ManagerID, e.EmployeeID, EmployeeLevel + 1
274     FROM HumanResources.Employee e
275         INNER JOIN DirectReports d
276         ON e.ManagerID = d.EmployeeID 
277 )
278 SELECT ManagerID, EmployeeID, EmployeeLevel 
279 FROM DirectReports 
280 WHERE EmployeeLevel <= 2 ;
281 GO
282 
283 USE AdventureWorks;
284 GO
285 WITH DirectReports(Name, Title, EmployeeID, EmployeeLevel, Sort)
286 AS (SELECT CONVERT(varchar(255), c.FirstName + ' ' + c.LastName),
287         e.Title,
288         e.EmployeeID,
289         1,
290         CONVERT(varchar(255), c.FirstName + ' ' + c.LastName)
291     FROM HumanResources.Employee AS e
292     JOIN Person.Contact AS c ON e.ContactID = c.ContactID 
293     WHERE e.ManagerID IS NULL
294     UNION ALL
295     SELECT CONVERT(varchar(255), REPLICATE ('' , EmployeeLevel) +
296         c.FirstName + ' ' + c.LastName),
297         e.Title,
298         e.EmployeeID,
299         EmployeeLevel + 1,
300         CONVERT (varchar(255), RTRIM(Sort) + '' + FirstName + ' ' + 
301                  LastName)
302     FROM HumanResources.Employee as e
303     JOIN Person.Contact AS c ON e.ContactID = c.ContactID
304     JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
305     )
306 SELECT EmployeeID, Name, Title, EmployeeLevel
307 FROM DirectReports 
308 ORDER BY Sort;
309 GO
310 
311 USE AdventureWorks;
312 GO
313 --Creates an infinite loop
314 WITH cte (EmployeeID, ManagerID, Title) as
315 (
316     SELECT EmployeeID, ManagerID, Title
317     FROM HumanResources.Employee
318     WHERE ManagerID IS NOT NULL
319   UNION ALL
320     SELECT cte.EmployeeID, cte.ManagerID, cte.Title
321     FROM cte 
322     JOIN  HumanResources.Employee AS e 
323         ON cte.ManagerID = e.EmployeeID
324 )
325 --Uses MAXRECURSION to limit the recursive levels to 2
326 SELECT EmployeeID, ManagerID, Title
327 FROM cte
328 OPTION (MAXRECURSION 2);
329 GO
330 
331  
332 
333 USE AdventureWorks;
334 GO
335 WITH cte (EmployeeID, ManagerID, Title)
336 AS
337 (
338     SELECT EmployeeID, ManagerID, Title
339     FROM HumanResources.Employee
340     WHERE ManagerID IS NOT NULL
341   UNION ALL
342     SELECT  e.EmployeeID, e.ManagerID, e.Title
343     FROM HumanResources.Employee AS e
344     JOIN cte ON e.ManagerID = cte.EmployeeID
345 )
346 SELECT EmployeeID, ManagerID, Title
347 FROM cte;
348 GO
349 
350 
351 USE AdventureWorks;
352 GO
353 WITH Parts(AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS
354 (
355     SELECT b.ProductAssemblyID, b.ComponentID, b.PerAssemblyQty,
356         b.EndDate, 0 AS ComponentLevel
357     FROM Production.BillOfMaterials AS b
358     WHERE b.ProductAssemblyID = 800
359           AND b.EndDate IS NULL
360     UNION ALL
361     SELECT bom.ProductAssemblyID, bom.ComponentID, p.PerAssemblyQty,
362         bom.EndDate, ComponentLevel + 1
363     FROM Production.BillOfMaterials AS bom 
364         INNER JOIN Parts AS p
365         ON bom.ProductAssemblyID = p.ComponentID
366         AND bom.EndDate IS NULL
367 )
368 SELECT AssemblyID, ComponentID, Name, PerAssemblyQty, EndDate,
369         ComponentLevel 
370 FROM Parts AS p
371     INNER JOIN Production.Product AS pr
372     ON p.ComponentID = pr.ProductID
373 ORDER BY ComponentLevel, AssemblyID, ComponentID;
374 GO
375 

 

posted @ 2010-04-13 17:07  ®Geovin Du Dream Park™  阅读(324)  评论(0编辑  收藏  举报