SQL Server 2005 Hierarchies WITH Common Table Expressions

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 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值