【问题标题】:how would you get many top root?你怎么会得到很多顶级根?
【发布时间】:2009-10-02 11:35:11
【问题描述】:

我有一个父/子关系表,多对多

parentid int not null
childid int not null

假设我有公司 a、b、c、d、e

a
..b
....c
..c
d
..e
....b
......c

我得到这个查询以返回一个顶级父母

FUNCTION [dbo].[getRootCompagny] 
(
    @root int
)
RETURNS int
AS
BEGIN
DECLARE @parent int

SELECT @parent = companyparentid from companyrelation where companychildid = @root
if @parent is not null
   set @root = dbo.getRootCompagny(@parent)

RETURN @root
END

如果我通过b,我只会得到

a
..b
....c
..c

因为我写的查询只能管理一个父级。 您将如何解决它以获取整棵树,就像第一棵树一样?

这是我的 CTE

    PROCEDURE [dbo].[GetCompanyRelation]
    @root int
AS
BEGIN
    SET NOCOUNT ON;

            set @root = dbo.getRootCompagny(@root)

    WITH cieCTE(CompanyChildid, CompanyParentid, depth, sortcol)
        AS
        (
            -- root member
            SELECT @root
                    , null 
                    , 0
                    , CAST(@root AS VARBINARY(900))


            UNION ALL

            -- recursive member
            SELECT R.CompanyChildid
                    , R.CompanyParentid
                    , C.depth+1
                    , CAST(sortcol + CAST(R.CompanyChildid AS BINARY(4)) AS VARBINARY(900))
            FROM CompanyRelation AS R JOIN cieCTE AS C ON R.CompanyParentid = C.CompanyChildid
        )

        -- outer query
        SELECT cieCTE.depth
                , cieCTE.CompanyChildid as ChildID
                , cieCTE.CompanyParentid as ParentId
                , company.[name] as [Name]
        FROM cieCTE inner join company on cieCTE.CompanyChildid = company.companyid
        ORDER BY sortcol
END

最后,按照上面的逻辑,我得到了a,如何得到a,d?

【问题讨论】:

  • 你能举一个表中数据的例子吗,当我看到这个时,CTE 可能导致给定 aboce (e->b) 的数据无限循环,将与 (b-> c)我认为不需要?
  • @astander,它不应该在我的示例中创建一个无限循环,但是它可能会发生,我会在重新创建完整的树后处理它

标签: sql-server-2005 common-table-expression


【解决方案1】:

好的,那你看看这个。它给出了缩进和完整的树路径

    DECLARE @Table TABLE(
        ID VARCHAR(10),
        ParentID VARCHAR(10)
)

--INSERT INTO @Table (ID,ParentID) SELECT 'a', NULL
INSERT INTO @Table (ID,ParentID) SELECT 'b', 'a'
INSERT INTO @Table (ID,ParentID) SELECT 'c', 'a'
INSERT INTO @Table (ID,ParentID) SELECT 'c', 'b'

--INSERT INTO @Table (ID,ParentID) SELECT 'd', NULL
INSERT INTO @Table (ID,ParentID) SELECT 'e', 'd'
INSERT INTO @Table (ID,ParentID) SELECT 'b', 'e'

DECLARE @Start VARCHAR(10)
SELECT @Start = 'e'

;WITH   roots AS (
        SELECT  *
        FROM    @Table
        WHERE   ID = @Start
        UNION   ALL
        SELECT  DISTINCT
                NULL,
                ParentID
        FROM    @Table
        WHERE   ParentID = @Start
        AND     ParentID NOT IN ( SELECT ID FROM @Table)
        UNION ALL
        SELECT  t.*
        FROM    @Table t INNER JOIN
                roots r ON t.ID = r.ParentID
)
,       layers AS(
        SELECT  ParentID AS ID,
                CAST(NULL AS VARCHAR(10)) AS ParentID,
                CAST('' AS VARCHAR(MAX)) AS DisplayDepth,
                CAST(ParentID + '\' AS VARCHAR(MAX)) AS LayerPath
        FROM    roots
        WHERE   ParentID NOT IN ( SELECT ID FROM @Table)
        UNION   ALL
        SELECT  t.*,
                DisplayDepth + '[-]',
                LayerPath + t.ID + '\'
        FROM    @Table t INNER JOIN
                layers l ON t.ParentID = l.ID
)
SELECT  *
FROM    layers
ORDER BY LayerPath

这就是你的想法吗?

【讨论】:

  • 你得到 +1 因为它是我想要的一半,现在如果我将 B 传递给该过程,我需要重新创建完整的树,如何找到 A 和 D?
  • 我已经稍微改变了答案,看看,我先找到根,从那里开始工作......
  • @astander,还有一件事,在你的例子中你允许 NULL,我不能改变数据库,在我的数据库中,我不能有 NULL。那么如果只删除两个带有null的插入,如何使它工作呢?
  • 那么你如何确定什么是根,你的根有什么 parentid?
猜你喜欢
  • 2010-09-26
  • 2018-12-03
  • 2020-09-10
  • 2016-02-21
  • 2011-02-06
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多