【问题标题】:How to build parent-child hierarchies (starting from root) in SQL Server?如何在 SQL Server 中构建父子层次结构(从根开始)?
【发布时间】:2020-03-02 12:44:20
【问题描述】:

我正在尝试使用 SQL 服务器获取从根节点到其子节点的路径。

源数据如下:

Source Data

目标应该是这样的:

Target Data

由于我将在 ETL 工具中专门使用 ETL 转换来实现此功能,因此我希望在不使用 CONNECT BY 等效方法的情况下实现此输出。下面的查询让我得到了结果和更多的记录:

select case when level02.geography_02 is not NULL
    then '3'
    else case when level01.geography_02 is not null
                then '2'
                else case when root.geography_02 is not null
                    then '1'
                    end 
        end
end as levels,
root.geography_01 as root, root.geography_02 as super_parent,
case when level01.geography_02 is not null
        then level01.geography_02
        else ''
        end as parent,
case when level02.geography_02 is not null
        then level02.geography_02
        else ''
        end as child
from geo_table root
left join geo_table level01
on root.geography_02 = level01.geography_01
left join geo_table level02
on level01.geography_02 = level02.geography_01

请问如何获得所需的输出?

【问题讨论】:

  • 您说您想使用 ETL 工具来实现这一点,但是,您上面的解决方案或尝试是基于 T-SQL 的。如果你想要一个 ETL 工具解决方案,你应该标记你正在使用的 ETL 工具。你上面的有什么问题?级别的数量是已知的,还是可以有更多?
  • 感谢您的回复。有一次,我准备好 SQL,我将在 Informatica 中设计它。我已经用 SQL Server 标记了这个问题,因为我知道如何使用简单的连接来完成这个问题。现在,Oracle 中的 CONNECT BY 提供了一种非常简单的方法来实现这一点。我假设会有一个等效的 SQL 服务器。但是,在 Informatica 中没有直接等效的 CONNECT 转换,因此我必须使用我希望避免的 SQL 覆盖。
  • 这能回答你的问题吗? stackoverflow.com/questions/959804/…
  • SQL 上面给了我一些不正确级别的额外记录:Levels Root Super Parent Parent Child 2 England London Greenwich 2 England London Mayfair 1 England Manchester 1 England Birmingham 1 London Greenwich 1 London Mayfair
  • 是的,您只有多个顶级节点,从那些(其父地理为 NULL)开始,您可以一起探索所有树。使用硬编码连接或递归 CTE。嵌套集也能很好地处理这个问题

标签: sql sql-server parent-child sql-server-2017


【解决方案1】:

我认为你只需要一些过滤。也就是说,您的查询的其余部分也可以稍微简化一下——尤其是使用COALESCE()

select (case when level02.geoghraphy_02 is not NULL then '3'
             when level01.geoghraphy_02 is not null then '2'
             when root.geoghraphy_02 is not null then '1'
        end) as levels,
       root.geoghraphy_01 as root,
       root.geoghraphy_02 as super_parent,
       coalesce(level01.geography_02, '') as parent,
       coalesce(level02.geography_02, '') as child
from geo_table root left join
     geo_table level01
     on root.geography_02 = level01.geography_01 left join
     geo_table level02
     on level01.geography_02 = level02.geography_01
where not exists (select 1
                  from geo_table gt
                  where gt.geography_02 = root.geography_01
                 );

基本上,您只需要将“根”限制为实际的根记录。您实际上已经处理了逻辑中更棘手的部分(在我看来)。

【讨论】:

  • 感谢@Gordon 的快速回复。看起来这个过滤器可以很好地完成这项工作。我会检查并回复你。
猜你喜欢
  • 1970-01-01
  • 2018-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多