2012-10-31 38 views
2

如何查詢此父級子級別以生成級別在其自己的列中的結果集?樣本數據:如何使用cte查詢和解析相鄰列表層次結構?

SET NOCOUNT ON; 
USE Tempdb; 

IF OBJECT_ID('dbo.Employees', 'U') IS NOT NULL DROP TABLE dbo.Employees; 

CREATE TABLE dbo.Employees 
(
    empid INT   NOT NULL PRIMARY KEY, 
    mgrid INT   NULL  REFERENCES dbo.Employees, 
    empname VARCHAR(25) NOT NULL, 
    salary MONEY  NOT NULL, 
    CHECK (empid <> mgrid), 
    CHECK (empid > 0) 
); 

CREATE UNIQUE INDEX idx_unc_mgrid_empid ON dbo.Employees(mgrid, empid); 

INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES 
    (1, NULL, 'David' , $10000.00), 
    (2, 1, 'Eitan' , $7000.00), 
    (3, 1, 'Ina' , $7500.00), 
    (4, 2, 'Seraph' , $5000.00), 
    (5, 2, 'Jiru' , $5500.00), 
    (6, 2, 'Steve' , $4500.00), 
    (7, 3, 'Aaron' , $5000.00), 
    (8, 5, 'Lilach' , $3500.00), 
    (9, 7, 'Rita' , $3000.00), 
    (10, 5, 'Sean' , $3000.00), 
    (11, 7, 'Gabriel', $3000.00), 
    (12, 9, 'Emilia' , $2000.00), 
    (13, 9, 'Michael', $2000.00), 
    (14, 9, 'Didi' , $1500.00); 

select * from dbo.Employees 
go  

;WITH Tree (empid, mgrid, lv) 
AS (

SELECT empid, mgrid, 1 
FROM Employees 
WHERE mgrid IS NULL 

UNION ALL 

SELECT E.empid, E.mgrid, lv + 1 
FROM Employees AS E 
JOIN Tree 
ON E.mgrid= Tree.empid 
) 
SELECT empid, mgrid, lv 
FROM Tree 
ORDER BY Lv, empid 

結果表應該有一個像

+-------+-----+--------+--------+--------+--------+--------+ 
| empid | lvl | level1 | level2 | level3 | level4 | level5 | 
+-------+-----+--------+--------+--------+--------+--------+ 
|  1 | 1 |  1 | NULL | NULL | NULL | NULL | 
|  2 | 2 |  1 | 2  | NULL | NULL | NULL | 
|  3 | 2 |  1 | 3  | NULL | NULL | NULL | 
|  4 | 3 |  1 | 2  | 4  | NULL | NULL | 
|  5 | 3 |  1 | 2  | 5  | NULL | NULL | 
|  6 | 3 |  1 | 2  | 6  | NULL | NULL | 
|  7 | 3 |  1 | 3  | 7  | NULL | NULL | 
|  8 | 4 |  1 | 2  | 5  | 8  | NULL | 
|  9 | 4 |  1 | 3  | 7  | 9  | NULL | 
| 10 | 4 |  1 | 2  | 5  | 10  | NULL | 
| 11 | 4 |  1 | 3  | 7  | 11  | NULL | 
| 12 | 5 |  1 | 3  | 7  | 9  | 12  | 
| 13 | 5 |  1 | 3  | 7  | 9  | 13  | 
| 14 | 5 |  1 | 3  | 7  | 9  | 14  | 
+-------+-----+--------+--------+--------+--------+--------+ 
+1

你不說清楚應該在'level1'..'level5'列什麼。你可以使用示例輸入數據給出一個示例結果集嗎? * [另外,你是否知道**你將只需要5個關卡?] * – MatBailie

+0

是的,我知道,我只需要那5個關卡。 – jrara

回答

4

您的示例數據的結構,使問題更加清晰。

; with Tree as 
     (
     SELECT empid 
     ,  mgrid 
     ,  1 as lv 
     ,  1 as level1 
     ,  null as level2 
     ,  null as level3 
     ,  null as level4 
     ,  null as level5 
     FROM Employees 
     WHERE mgrid IS NULL 
     UNION ALL 
     SELECT E.empid 
     ,  E.mgrid 
     ,  T.lv + 1 
     ,  T.level1 
     ,  case when T.lv = 1 then E.empid else t.level2 end 
     ,  case when T.lv = 2 then E.empid else t.level3 end 
     ,  case when T.lv = 3 then E.empid else t.level4 end 
     ,  case when T.lv = 4 then E.empid else t.level5 end 
     FROM Employees AS E 
     JOIN Tree T 
     ON  E.mgrid = T.empid 
     ) 
select * 
from Tree 

Example at SQL Fiddle.

+0

這似乎沒有產生正確的結果集。 – jrara

+0

@jrara:你說的對,關係顛倒了。新版本應該更好地工作:#12報告9,9到7,7到3,3到1. – Andomar

+0

謝謝,我編輯了正確的結果集的問題。 – jrara

0

隨着樞軸:當你潛你可以收集管理水平?

;WITH Tree (empid, mgrid, lv) 
AS (

SELECT empid, mgrid, 1 
FROM @Employees 
WHERE mgrid IS NULL 

UNION ALL 

SELECT E.empid, E.mgrid, lv + 1 
FROM @Employees AS E 
JOIN Tree 
ON E.mgrid= Tree.empid 
) 
select * 
from 
Tree 
pivot 
(count(empid) for lv in ([1],[2],[3],[4],[5]))p 
+0

This似乎沒有產生正確的結果集。 – jrara

+0

那麼什麼是正確的結果集?如何計算網格中的數字? – podiluska

+0

我編輯了這個問題。 – jrara

2
;WITH Tree (empid, level, level1, level2, level3, level4, level5) 
AS (

SELECT empid, 1, empid, NULL, NULL, NULL, NULL 
FROM Employees 
WHERE mgrid IS NULL 

UNION ALL 

SELECT E.empid, T.level + 1, 
     CASE WHEN T.level+1 = 1 THEN E.empid ELSE T.level1 END, 
     CASE WHEN T.level+1 = 2 THEN E.empid ELSE T.level2 END, 
     CASE WHEN T.level+1 = 3 THEN E.empid ELSE T.level3 END, 
     CASE WHEN T.level+1 = 4 THEN E.empid ELSE T.level4 END, 
     CASE WHEN T.level+1 = 5 THEN E.empid ELSE T.level5 END 
FROM Employees AS E 
JOIN Tree T 
ON E.mgrid= T.empid 
) 
SELECT empid, level, level1, level2, level3, level4, level5 
FROM Tree