2012-12-05 23 views
9

मैं आत्म-संदर्भ तालिका का विश्लेषण करने के लिए निम्नलिखित सामान्य तालिका अभिव्यक्ति का उपयोग कर रहा हूं। लेकिन CTE काम नहीं करता है, उत्पादन और अनंत लूप और एक त्रुटि उत्पन्न करता है:स्वयं-संदर्भ तालिका को पार्स करते समय सीटीई में अनंत लूप

Msg 530, Level 16, State 1, Line 1 The statement terminated. The maximum recursion 100 has been exhausted before statement completion.

यह कैसे 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 > 0) 
); 

INSERT INTO dbo.Employees(empid, mgrid, empname, salary) VALUES 
    (1, 1, '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 empid = 1 and mgrid = 1 
     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 |  1 | 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  | 
+-------+-------+----+--------+--------+--------+--------+--------+ 

उत्तर

18

अनंत लूप के कारण पहले रिकॉर्ड जहां empid=mgrid है। इस समस्या को संभालने के लिए आपको mgrid स्टोर करने के लिए संचयी फ़ील्ड (levels इस उदाहरण में) शामिल करना चाहिए, आपने पहले ही संसाधित कर लिया है और जांच कर ली है कि emid लूप से बचने के लिए पहले से ही इस सूची में है या नहीं। यहाँ

with Tree as 
     (
     SELECT empid 
     ,  mgrid 
     ,  1 as lv 
     ,  1 as level1 
     ,  null as level2 
     ,  null as level3 
     ,  null as level4 
     ,  null as level5 
     ,  cast(mgrid as varchar(max)) levels 
     FROM Employees 
     WHERE empid = 1 and mgrid = 1 
     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 
     ,  T.levels+','+cast(E.mgrid as varchar(max)) levels 

      FROM Employees AS E 
     JOIN Tree T 
     ON  E.mgrid = T.empid 
       and (','+T.levels+',' 
         not like 
        '%,'+cast(E.empid as varchar(max))+',%') 
     ) 
select * 
from Tree 
order by empid 

और SQLFiddle demo

+2

शानदार जवाब और अच्छा सवाल के लिए +1 है;) –

+0

मैं जाँच माता-पिता के रिश्ते उस तरह के लिए XML का उपयोग करने के लिए और अधिक सलाह देंगे:

यहाँ एक प्रश्न है –