2017-04-21 85 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 | 
+------------+--------------+--------+------------+-----------------+-------+------+