博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL Server 2005 Hierarchies WITH Common Table Expressions
阅读量:6691 次
发布时间:2019-06-25

本文共 8624 字,大约阅读时间需要 28 分钟。

ExpandedBlockStart.gif
代码
  1 
create
 
table
 Employee
  2 
(
  3 
Id 
INT
 
IDENTITY
(
1
,
1
PRIMARY
 
KEY
  4 
[
Name
]
 
varchar
(
30
null
  5 
JobTitle 
varchar
(
30
null
  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 

 

转载地址:http://tthao.baihongyu.com/

你可能感兴趣的文章
Android各种访问权限Permission详解
查看>>
web前端开发中浏览器兼容问题(五)
查看>>
我的友情链接
查看>>
博为峰Java技术文章 ——JavaSE Swing BoxLayout布局管理器I
查看>>
(26)改变自动扫描的包【从零开始学Spring Boot】
查看>>
es6函数总结
查看>>
QT创建与QT无关的纯C++程序和动态/静态库
查看>>
并查集(Union-Find)算法介绍
查看>>
MySQL主从配置
查看>>
java实现的web网络书店
查看>>
Shell脚本介绍(资源)
查看>>
分享HTML5自动化构建工具gulp使用方法步骤
查看>>
BootStrap 资源汇总
查看>>
一次、二次、三次指数平滑计算思想及代码
查看>>
13.2管理网络冗余与数据存储群集
查看>>
阿里开源的 java 诊断工具—— Arthas
查看>>
Angular CLI 创建你的第一个 Angular 示例程序
查看>>
深入理解javascript原型和闭包(16)——完结
查看>>
如何点击每一列的时候alert其index
查看>>
【原创翻译】类型
查看>>