2008-10-24 135 views
11

當我在一家Oracle商店工作的時候,我認爲CONNECT_BY是理所當然的。現在我堅持使用SQL Server 2005,並有一些討厭的對象層次結構。具體而言,我們有一個自引用表,其中所有子記錄都有一個包含其父代的ID的列。目前,我們有一種將孩子映射到層次結構中的視圖,以及一個可以讓父母與子女聯繫起來的令人討厭的查詢。雖然這種方法有效,但它遠離優雅和污點。我只是好奇其他人如何從SQL Server 2005中檢索分層數據。SQL Server 2005中的分層查詢

回答

1

在SQL Server 2005中,您可以使用Common Table Expressions(CTE)。

+0

遞歸力與()你。哈哈哈。 – 2008-10-24 22:54:34

+0

你能舉個例子嗎? – 2008-11-10 21:55:51

25

這將創建典型的分層表並使用CTE選擇層次結構併爲每個項目創建路徑。

CREATE TABLE tblHierarchy (ID int, ParentID int NULL, Name varchar(128)); 

INSERT INTO tblHierarchy VALUES (1, NULL, '1'); 
INSERT INTO tblHierarchy VALUES (2, NULL, '2'); 
INSERT INTO tblHierarchy VALUES (3, NULL, '3'); 
INSERT INTO tblHierarchy VALUES (4, 1, '1.1'); 
INSERT INTO tblHierarchy VALUES (5, 1, '1.2'); 
INSERT INTO tblHierarchy VALUES (6, 4, '1.1.1'); 

WITH Parent AS 
(
    SELECT 
     ID, 
     ParentID, 
     Name AS Path 
    FROM 
     tblHierarchy 
    WHERE 
     ParentID IS NULL 

    UNION ALL 

    SELECT 
     TH.ID, 
     TH.ParentID, 
     CONVERT(varchar(128), Parent.Path + '/' + TH.Name) AS Path 
    FROM 
     tblHierarchy TH 
    INNER JOIN 
     Parent 
    ON 
     Parent.ID = TH.ParentID 
) 
SELECT * FROM Parent 

OUTPUT:

ID ParentID Path 
1 NULL  1 
2 NULL  2 
3 NULL  3 
4 1  1/1.1 
5 1  1/1.2 
6 4  1/1.1/1.1.1 
3

僅供參考。 SQL Server 2008支持新的數據類型Hierarchy ID

2

閱讀:

http://www.sitepoint.com/article/hierarchical-data-database/2/

它應該給你一些想法...

+0

是的,嵌套集絕對是RDBMS中無限層次結構的一種方式。 Sitepoint的描述使其聽起來比實際更復雜一些,並且可以簡化實現,例如。通過'排序'和'下一個兄弟姐妹的排名'而不是'左'和'右'。 – bobince 2008-10-24 23:34:48

3

曾使用這兩個,我發現CONNECT BY是較爲靈活,更容易比CTE的使用。這個問題與我幾周前回答的問題並不相同。請參閱Here以獲取CONNECT BY和CTE的簡要比較,以及使用CTE查詢示例Here

0

要首先遍歷層次的深度,然後下一個同級的水平,可用於 CTE:

declare @tempTable TABLE 
(
    ORGUID int, 
    ORGNAME nvarchar(100), 
    PARENTORGUID int, 
    ORGPATH nvarchar(max) 
) 

;WITH RECORG(ORGuid, ORGNAME, PARENTORGUID, ORGPATH) 
as 
(
    select 
     org.UID, 
     org.Name, 
     org.ParentOrganizationUID, 
     dbo.fGetOrganizationBreadcrumbs(org.UID) 
    from Organization org 
    where org.UID =1 

    union all 

    select 
     orgRec.UID, 
     orgRec.Name, 
     orgRec.ParentOrganizationUID, 
     dbo.fGetOrganizationBreadcrumbs(orgRec.UID) 
    from Organization orgRec 
    inner join RECORG recOrg on orgRec.ParentOrganizationUID = recOrg.ORGuid 

) 
insert into @tempTable(ORGUID, ORGNAME, PARENTORGUID,ORGPATH) 

select ORGUID, ORGNAME, PARENTORGUID,ORGPATH 
from RECORG rec 

select * 
from @tempTable where ORGUID in(select MIN(tt.ORGUID) 
           from @tempTable tt 
           group by tt.PARENTORGUID)