2012-03-07 80 views
0

我有一个自我引用表来存储的层级值的树基地的后裔(路),以显示他们在一个TreeView或等等,根据詹姆斯·克劳利文章(Tree structures in ASP.NET and SQL Server检索多个值

Our table would look something like this: 

Id ParentId  Name  Depth Lineage 
1 NULL  Root Node  0  /1/ 
2 1   Child A   1  /1/2/ 
3 1   Child B   1  /1/3/ 
4 1   Child C   1  /1/4/ 
5 2   Child D   2  /1/2/5/ 

获取一个节点的路径(例如ID = 5),他提出以下查询表对

SELECT * 
FROM dfTree 
WHERE (SELECT lineage 
     FROM dfTree 
     WHERE id = 5) LIKE lineage + '%' 

结果将是:

Id ParentId  Name  Depth Lineage 
1 NULL  Root Node  0  /1/ 
2 1   Child A   1  /1/2/ 
5 2   Child D   2  /1/2/5/ 

而且是可以接受的

但如何有当有多个ID,我想有自己的路径的结果集?因此,例如在上面的例子中,而不是编号= 5我想传递多个值是这样的:

SELECT * 
FROM dfTree 
WHERE (SELECT lineage 
     FROM dfTree 
     WHERE id IN (5,6,8,9)) LIKE lineage + '%' 

但上述说法没有任何意义,这是无效的SQL服务器表达
我怎么能解决这个问题问题?
在此先感谢

+0

你想记录,其中的ID是你正在寻找的是顶级家长,孩子还是血统中的任何地方? – 2012-03-07 12:37:31

回答

1

此查询...

SELECT DISTINCT T2.* 
FROM 
    (
     SELECT lineage 
     FROM dfTree 
     WHERE id IN (4, 5) 
    ) T1 
    JOIN dfTree T2 
    ON 
     T1.Lineage LIKE T2.Lineage + '%' 

...返回您的测试数据结果如下:

Id ParentId Name  Depth Lineage 
1 NULL  Root Node 0  /1/ 
2 1   Child A  1  /1/2/ 
4 1   Child C  1  /1/4/ 
5 2   Child D  2  /1/2/5/ 

正如你可以看到,所有的路径都“合并“一起 - 例如,路径组件Id=1属于路径:/1/4/和路径:/1/2/5/,但只存在于结果集中一次。


一个另一方面,如果你需要不同的路径来区分,你需要做这样的事情:

SELECT T2.*, T1.Id LeafId 
FROM 
    (
     SELECT id, lineage 
     FROM dfTree 
     WHERE id IN (4, 5) 
    ) T1 
    JOIN dfTree T2 
    ON 
     T1.Lineage LIKE T2.Lineage + '%' 

结果:

Id ParentId Name  Depth Lineage LeafId 
1 NULL  Root Node 0  /1/  4 
4 1   Child C  1  /1/4/  4 
1 NULL  Root Node 0  /1/  5 
2 1   Child A  1  /1/2/  5 
5 2   Child D  2  /1/2/5/ 5 

在这种情况下,每条路径都由其叶子标识。这假设没有钻石形状的依赖关系(即,这是一棵真正的树,而不仅仅是任何DAG);如果,那么您需要使用T1.Lineage而不是T1.Id来标识路径。

1

如果您正在运行SQL Server 2005或更高版本,你可以在子查询移到CTE:

; with cte as (
    SELECT lineage 
    FROM dfTree 
    WHERE id IN (5,6,8,9) 
) 
SELECT d.* 
FROM dfTree d 
inner join cte on cte.lineage like d.lineage + '%' 

或者只是重组的子查询:

SELECT d.* 
FROM dfTree d 
inner join (
    SELECT lineage 
    FROM dfTree 
    WHERE id IN (5,6,8,9) 
) s on s.lineage like d.lineage + '%'