2012-11-20 8 views
2

J'ai une requête qui produit une hiérarchie aplatie à partir d'une table parent-enfant (auto-jointure, liste adjacente). Le problème est que cette requête produit des valeurs NULL pour les niveaux qui n'ont aucun enfant. Maintenant, mon intention est de «remplir» ces niveaux pour produire une table qui ne contient aucune valeur NULL dans les colonnes de niveau. Comment dois-je modifier cette requête?Liste adjacente et requête récursive utilisant un CTE, comment remplir?

données Exemple:

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); 

requête fournie par @Andomar

; 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 

Cela donne

+-------+--------+----+--------+--------+--------+--------+--------+ 
| 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  | 
+-------+--------+----+--------+--------+--------+--------+--------+ 

mais l'idée est de parvenir à ce

+-------+--------+----+--------+--------+--------+--------+--------+ 
| 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

Que voulez-vous dire? – jrara

Répondre

2

Ajoutez simplement ci-dessous après le CTE Arbre

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 

enter image description here

+0

solution très intelligente, fonctionne dans ce cas! – jrara

2

juste un simple essai pour modifier les résultats comme vous le souhaitez serait d'utiliser coalesce() dans la dernière sélection.

see sql-fiddle here

+0

Je n'ai jamais su qu'il y avait un violon sql là-bas. C'est génial. – Mike

+0

En fait, ce n'est pas un jeu de résultats correct. – jrara

+0

fixe fiddle-demo – Nico

1

Je trouve que cela fonctionne aussi:

; 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 
Questions connexes