我有一个查询,它从父子表(自连接,相邻列表)生成扁平层次结构。问题是此查询为没有任何子级的级别生成NULL。现在我的意图是“回填”这些级别以生成一个表,该表在级别列中不包含任何NULL值。我该如何修改此查询?
示例数据:
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);
提供的查询
; 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
order by empid
这会产生
+-------+--------+----+--------+--------+--------+--------+--------+
| EMPID | MGRID | LV | LEVEL1 | LEVEL2 | LEVEL3 | LEVEL4 | LEVEL5 |
+-------+--------+----+--------+--------+--------+--------+--------+
| 1 | (null) | 1 | 1 | (null) | (null) | (null) | (null) |
| 2 | 1 | 2 | 1 | 2 | (null) | (null) | (null) |
| 3 | 1 | 2 | 1 | 3 | (null) | (null) | (null) |
| 4 | 2 | 3 | 1 | 2 | 4 | (null) | (null) |
| 5 | 2 | 3 | 1 | 2 | 5 | (null) | (null) |
| 6 | 2 | 3 | 1 | 2 | 6 | (null) | (null) |
| 7 | 3 | 3 | 1 | 3 | 7 | (null) | (null) |
| 8 | 5 | 4 | 1 | 2 | 5 | 8 | (null) |
| 9 | 7 | 4 | 1 | 3 | 7 | 9 | (null) |
| 10 | 5 | 4 | 1 | 2 | 5 | 10 | (null) |
| 11 | 7 | 4 | 1 | 3 | 7 | 11 | (null) |
| 12 | 9 | 5 | 1 | 3 | 7 | 9 | 12 |
| 13 | 9 | 5 | 1 | 3 | 7 | 9 | 13 |
| 14 | 9 | 5 | 1 | 3 | 7 | 9 | 14 |
+-------+--------+----+--------+--------+--------+--------+--------+
但想法是实现这个目标
+-------+--------+----+--------+--------+--------+--------+--------+
| EMPID | MGRID | LV | LEVEL1 | LEVEL2 | LEVEL3 | LEVEL4 | LEVEL5 |
+-------+--------+----+--------+--------+--------+--------+--------+
| 1 | (null) | 1 | 1 | 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 | 2 | 2 | 2 | 2 |
| 3 | 1 | 2 | 1 | 3 | 3 | 3 | 3 |
| 4 | 2 | 3 | 1 | 2 | 4 | 4 | 4 |
| 5 | 2 | 3 | 1 | 2 | 5 | 5 | 5 |
| 6 | 2 | 3 | 1 | 2 | 6 | 6 | 6 |
| 7 | 3 | 3 | 1 | 3 | 7 | 7 | 7 |
| 8 | 5 | 4 | 1 | 2 | 5 | 8 | 8 |
| 9 | 7 | 4 | 1 | 3 | 7 | 9 | 9 |
| 10 | 5 | 4 | 1 | 2 | 5 | 10 | 10 |
| 11 | 7 | 4 | 1 | 3 | 7 | 11 | 11 |
| 12 | 9 | 5 | 1 | 3 | 7 | 9 | 12 |
| 13 | 9 | 5 | 1 | 3 | 7 | 9 | 13 |
| 14 | 9 | 5 | 1 | 3 | 7 | 9 | 14 |
+-------+--------+----+--------+--------+--------+--------+--------+
答案 0 :(得分:2)
只需一个简单的尝试就可以按照您希望的方式在最后一次选择中使用coalesce()
修改结果。
答案 1 :(得分:2)
在Tree CTE之后添加以下内容
Select empid,mgrid,lv,
level1 = coalesce(level1,Rn),
level2 = coalesce(level2,Rn),
level3 = coalesce(level3,Rn),
level4 = coalesce(level4,Rn),
level5 = coalesce(level5,Rn)
from
(select empid,mgrid,lv,level1,level2,level3,level4,level5,Row_Number()Over(Order By empid) as Rn
from Tree)x
答案 2 :(得分:1)
我发现这也有效:
; 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 empid,
mgrid,
lv,
level1,
level2 = coalesce(level2, level1),
level3 = coalesce(level3, level2, level1),
level4 = coalesce(level4, level3, level2, level1),
level5 = coalesce(level5, level4, level3, level2, level1)
from Tree
order by empid