2008-10-24 105 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)