2012-03-07 79 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 + '%'