【问题标题】:Identify the subsequent parents child hierarchy in table识别表中后续的父子层次结构
【发布时间】:2019-07-25 04:32:04
【问题描述】:

我在表中有父子关系。我想使用父子关系表填充一个新表,该表将包含子级和层次结构中的所有后续父级。

我一直在研究所提供的解决方案,但无法编写能够为我提供所需结果的查询。

以下代码可用于创建表和加载示例数据

create table DemoTable
(
    accountid bigint
    ,parentid bigint
    ,accountname nvarchar(128)
)
insert DemoTable(accountid,parentid,accountname)
select 1, null, 'Root'
union select 2, 1, 'Child1'
union select 3, 1, 'Child2'
union select 4, 1, 'Child3'
union select 5, 2, 'Child1.1'
union select 6, 2, 'Child1.2'
union select 7, 3, 'Child1.3'
union select 8, 7, 'Child1.3.7'
go

输出应该如下所示

accountid    parentid    hierarchyLevel
8    7    3
8    3    2
8    1    1
7    3    2
7    1    1
3    1    1
6    2    2
6    1    1
2    1    1

【问题讨论】:

  • 我不明白您想要的输出中的accountid 是如何生成的?为什么没有 5 作为accountid?
  • 我以 8 和 6 帐户 ID 作为样本。但是是的,根据层次结构,输出中也会出现 5。
  • 有什么建议吗?

标签: sql sql-server


【解决方案1】:

这可能会有所帮助....

DECLARE  @DemoTable table
(
    accountid bigint
    ,parentid bigint
    ,accountname nvarchar(128)
)
insert  @DemoTable(accountid,parentid,accountname)
select 1, null,    'Root'
union select 2, 1, 'Child1'
union select 3, 1, 'Child2'
union select 4, 1, 'Child3'
union select 5, 2, 'Child1.1'
union select 6, 2, 'Child1.2'
union select 7, 3, 'Child1.3'
union select 8, 7, 'Child1.3.7'

;WITH CTE
AS
(
SELECT accountid,parentid--,LEN(REPLACE(REPLACE(accountname,'.',''),'Child','')) hierarchyLevel
FROM @DemoTable
WHERE accountname <> 'Root'

UNION ALL

SELECT c.accountid ,d.parentid--,LEN(REPLACE(REPLACE(accountname,'.',''),'Child','')) hierarchyLevel
FROM @DemoTable d 
INNER JOIN CTE c ON d.accountid = c.parentid
WHERE d.accountname <> 'Root'

)
SELECT *,ROW_NUMBER() OVER( PARTITION  BY accountid  ORDER BY accountid ASC ,parentid ASC) hierarchyLevel
FROM CTE
order by accountid DESC ,parentid DESC --, CAST(hierarchyLevel as INT) DESC
option (maxrecursion 0)

【讨论】:

  • 嗨阿拉姆。我看到您已经使用长度 ti 来标识层次结构级别。如果不是这种情况怎么办。这是我准备的样本数据,但我不能将相同的概念与我的实际数据一起使用。对于那个很抱歉。否则我会得到我想要的输出。
  • 嗨,阿拉姆,这对我有用。你能给我一些参考,我可以在哪里学习 SQl。这非常好。
  • 您可以关注 kudvenkat - YouTube 和 Microsoft SQL Server 2012 圣经一书。
  • @Sunil,如果它适合您,请接受答案。
  • 你好@KhairulAlam。这是解决上述问题的好方法。为此+1!你能告诉我你为什么在这里使用option吗?另外,如果父子accountIds是递减的,那么如何计算层级呢?
【解决方案2】:

我们可以使用Common Table Expression (CTE)来解决这个问题。

首先,我们将使用递归 CTE 将每个孩子带到他们的父母身边。最初,我们将每个孩子的标签表示为 1。然后,我们递归地增加他们父母的数字。

因此,父母的标签价值会更高,而孩子的标签价值会更少。

然后我们通过使用accountId按照label值的降序进行分区得到行号(因为叶子的标签值更高)

通过这样做,我们得到了预期的数据。然后我们做了一些排序,以与问题中显示的预期输出相同的方式显示它。

代码如下和here is the live dbfiddle

create table DemoTable
(
    accountid bigint
    ,parentid bigint
    ,accountname nvarchar(128)
)
insert DemoTable(accountid,parentid,accountname)
select 1, null, 'Root'
union select 2, 1, 'Child1'
union select 3, 1, 'Child2'
union select 4, 1, 'Child3'
union select 5, 2, 'Child1.1'
union select 6, 2, 'Child1.2'
union select 7, 3, 'Child1.3'
union select 8, 7, 'Child1.3.7'
go

;WITH ChildParentHierarchy AS
(
    SELECT accountId, parentId, 1 AS label
    FROM DemoTable WHERE parentid IS NOT NULL

    UNION ALL

    SELECT cte.accountId, D.parentId, (cte.label + 1) AS label
    FROM DemoTable D
    INNER JOIN ChildParentHierarchy cte
    ON D.accountid = cte.parentid
    WHERE D.parentid IS NOT NULL
)

SELECT
    accountId, 
    parentId, 
    ROW_NUMBER() OVER (
        Partition BY accountId 
        ORDER BY label DESC
    ) AS hierarchyLevel
INTO #temp --we are storing the value of CTE
FROM ChildParentHierarchy
ORDER BY accountid DESC

--final result
SELECT * FROM #temp
ORDER BY accountid DESC, hierarchyLevel DESC

DROP TABLE #temp

希望对您有所帮助,谢谢!

【讨论】:

    【解决方案3】:

    您可以尝试此解决方案(根据您的架构更改字段名称):

      WITH CTE AS (
          SELECT accountid, ParentId,0 AS [Level], CAST(accountid AS varchar(1000)) AS Heirarchy,accountid AS TopParentId
          FROM dbo.DemoTable
          WHERE accountid IN (SELECT accountid FROM DemoTable WHERE ParentId IS NULL)
          UNION ALL
    
          SELECT mgr.accountid, mgr.ParentId, CTE.[Level] +1 AS [Level], 
                CAST(( CAST(mgr.accountid AS VARCHAR(1000)) + '>' + CTE.Heirarchy) AS varchar(1000)) AS Heirarchy, CTE.TopParentId
          FROM CTE
            INNER JOIN dbo.DemoTable AS mgr
              ON CTE.accountid = mgr.ParentId
        )
        select  * from cte order by heirarchy desc
    

    编辑
    这里加入了层次结构,得到每个id的层次关系。这并不完全是需要的,但可能会有所帮助。

    【讨论】:

    • 这不是我期望的输出。这个解决方案在很多地方都有,不是我想要的。
    • 然后解释一下你在找什么?
    • 请检查我正在寻找的输出。我提供了示例输出。子级的行数应与具有顺序的子级之上的层次结构一样多。在上面的示例中,8 的层次结构是 8 ---> 7--->3--->1。因此,我需要向每个级别报告 3 行 8 行,如上面的示例输出所示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    相关资源
    最近更新 更多