【问题标题】:Hierarchical Queries in SQL Server 2005SQL Server 2005 中的分层查询
【发布时间】:2010-09-19 03:05:34
【问题描述】:

当我在 Oracle 商店工作时,我认为 CONNECT_BY 是理所当然的。现在我坚持使用 SQL Server 2005 并且有一些讨厌的对象层次结构。具体来说,我们有一个自引用表,其中所有子记录都有一个带有其父 ID 的列。目前,我们有一个将子级映射到层次结构中的级别的视图和一个讨厌的查询,它可以完成繁重的工作以将父母与他们的孩子联系起来。虽然这种方法有效,但它远非优雅且带有污点。我只是好奇其他人如何从 SQL Server 2005 中检索分层数据。

【问题讨论】:

    标签: sql sql-server sql-server-2005


    【解决方案1】:

    这将创建您的典型分层表并使用 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
    

    输出:

    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
    

    【讨论】:

      【解决方案2】:

      同时使用了这两种方法后,我发现 CONNECT BY 比 CTE 更灵活、更易于使用。这个问题与我几周前回答的问题没有什么不同。有关 CONNECT BY 和 CTE 的简要比较,请参阅 Here;有关使用 CTE 的查询示例,请参阅 Here

      【讨论】:

      • MSSQL 中不存在 CONNECT BY 的运气。
      【解决方案3】:

      仅供参考。 SQL Server 2008 支持新的数据类型Hierarchy ID

      【讨论】:

        【解决方案4】:

        在 SQL Server 2005 中,您可以为此使用公用表表达式 (CTE)。

        【讨论】:

        • 递归的力量是 WITH() 你。哈哈哈。
        【解决方案5】:

        要先遍历层次结构的深度,然后再遍历下一个兄弟级别, 可以使用 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)
        

        【讨论】:

          猜你喜欢
          • 2010-10-03
          • 2021-07-12
          • 1970-01-01
          • 1970-01-01
          • 2011-01-25
          • 1970-01-01
          • 2012-11-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多