2017-04-21 83 views
1

我使用的是SQL Server 2012中,我有以下問題:申請遞歸左連接

我有這個表(類別):

IDCategory| CategoryDesc  | Father 
1   | R1    | 0 
2   | R1 - ST   | 1 
3   | R1 - CT   | 1 
4   | R1 - ST - SA  | 2 
5   | R1 - ST - CA 10 | 2 
6   | R1 - ST - CA 20 | 2 
7   | R1 - CT - CA  | 3 
8   | R1 - CT - SA  | 3 
9   | R2    | 0 
10  | R2 ST   | 9 
.   
.   
until R9   

而這一次(categoryDe​​finition類別):

IDCategory| First| Last 
1   | 0 | 300 
9   | 301 | 600 
.   
.   
.   

而且我使用下面的查詢,因爲我知道那裏是隻有3個層次:

SELECT 
cat3.IDCategory, 
cat.CategoryDesc AS title1, 
cat2.CategoryDesc AS title2, 
cat3.CategoryDesc AS title3, 
catdef.First, 
catdef.Last 
FROM Category as cat 
LEFT JOIN Category AS cat2 ON cat2.Father=cat.IDCategory 
LEFT JOIN Category AS cat3 ON cat3.Father=cat2.IDCategory 
INNER JOIN CategoryDefinition as catdef on cat.IDCategory = catdef.IDCategory 
WHERE cat3.IDCategory = 7 

查詢結果:

IDCategory| title1 | title2 |title3  |First|Last 
    7  | R1  | R1 - CT | R1 - CT - CA | 0 | 300 

但我怎麼能做出這種遞歸?在將來可能會出現新的級別(所以我不必爲出現的每個新級別添加新的左連接)。

謝謝!

+0

你真的想在自己的每個'title'柱?遞歸cte的動態支點似乎是一個壞主意。 – SqlZim

+0

@SqlZim你說的是隻顯示title3?而不是顯示所有3個標題? – fedee13

+0

@SqlZim我(據說)需要他們分開,因爲使用必須選擇每個級別。第一級別1(R1,R2,R3 ....),根據級別1我將顯示級別2(ST或CT)的選項,根據級別2,我會顯示級別3(ST - SA,ST - CA 10,ST - CA 20或CT - CA,CT - SA)。 – fedee13

回答

0

我至少可以與鄰接表的recusive CTE,建設物化路徑幫助:使用遞歸CTE

create table category (IDCategory int primary key,CategoryDesc varchar(32),Father int) 
insert into category values 
(1,'R1',0) 
,(2,'ST',1) 
,(3,'CT',1) 
,(4,'SA',3) 
,(5,'SA 10',2) 
,(6,'SA 20',2) 
,(7,'CA',2) 
,(8,'SA',2) 
,(9,'R2',0) 
,(10,'ST',9) 

;with cte as (
-- anchor elements: where Father = 0 
    select 
     IDCategory 
    , categoryDesc 
    , Father 
    , parentName = convert(varchar(32),null) 
    , path = convert(varchar(128),categoryDesc) 
    from category 
    where Father = 0 
    -- recursion begins here 
    union all 
    select 
     c.IDCategory 
    , c.categoryDesc 
    , c.Father 
    , parentName = p.categoryDesc 
    , path = convert(varchar(128),p.path+' - '+c.categoryDesc) 
    from category c 
    inner join cte as p on c.Father= p.IDCategory 
) 
-- we select all the results 
select cte.* 
from cte 
order by idCategory 

此表退貨:

+------------+--------------+--------+------------+-----------------+ 
| IDCategory | categoryDesc | Father | parentName |  path  | 
+------------+--------------+--------+------------+-----------------+ 
|   1 | R1   |  0 | NULL  | R1    | 
|   2 | ST   |  1 | R1   | R1 - ST   | 
|   3 | CT   |  1 | R1   | R1 - CT   | 
|   4 | SA   |  3 | CT   | R1 - CT - SA | 
|   5 | SA 10  |  2 | ST   | R1 - ST - SA 10 | 
|   6 | SA 20  |  2 | ST   | R1 - ST - SA 20 | 
|   7 | CA   |  2 | ST   | R1 - ST - CA | 
|   8 | SA   |  2 | ST   | R1 - ST - SA | 
|   9 | R2   |  0 | NULL  | R2    | 
|   10 | ST   |  9 | R2   | R2 - ST   | 
+------------+--------------+--------+------------+-----------------+ 

添加加入到遞歸CTE的錨:

;with cte as (
-- anchor elements: where Father = 0 
    select 
     c.IDCategory 
    , c.categoryDesc 
    , c.Father 
    , parentName = convert(varchar(32),null) 
    , path = convert(varchar(128),c.categoryDesc) 
    , cd.First 
    , cd.Last 
    from category c 
    inner join CategoryDefinition cd 
     on c.IdCategory=cd.IdCategory 
    where Father = 0 
    -- recursion begins here 
    union all 
    select 
     c.IDCategory 
    , c.categoryDesc 
    , c.Father 
    , parentName = p.categoryDesc 
    , path = convert(varchar(128),p.path+' - '+c.categoryDesc) 
    , p.First 
    , p.Last 
    from category c 
    inner join cte as p on c.Father= p.IDCategory 
) 
select cte.* 
from cte 
--where IdCategory = 7 
order by idCategory 

rextester演示:http://rextester.com/POSVP81190

回報:

+------------+--------------+--------+------------+-----------------+-------+------+ 
| IDCategory | categoryDesc | Father | parentName |  path  | First | Last | 
+------------+--------------+--------+------------+-----------------+-------+------+ 
|   1 | R1   |  0 | NULL  | R1    |  0 | 300 | 
|   2 | ST   |  1 | R1   | R1 - ST   |  0 | 300 | 
|   3 | CT   |  1 | R1   | R1 - CT   |  0 | 300 | 
|   4 | SA   |  3 | CT   | R1 - CT - SA |  0 | 300 | 
|   5 | SA 10  |  2 | ST   | R1 - ST - SA 10 |  0 | 300 | 
|   6 | SA 20  |  2 | ST   | R1 - ST - SA 20 |  0 | 300 | 
|   7 | CA   |  2 | ST   | R1 - ST - CA |  0 | 300 | 
|   8 | SA   |  2 | ST   | R1 - ST - SA |  0 | 300 | 
|   9 | R2   |  0 | NULL  | R2    | 301 | 600 | 
|   10 | ST   |  9 | R2   | R2 - ST   | 301 | 600 | 
+------------+--------------+--------+------------+-----------------+-------+------+