【问题标题】:Make parent and child hierarchy with records for parents as well as children使用父母和孩子的记录制作父母和孩子层次结构
【发布时间】:2020-06-03 22:23:09
【问题描述】:

我有一个父子 id_table 层次结构 - 例如

|parent|child|
|------|-----|
|      |    0|
|     0|    1|
|     0|    2|
|     0|    3|
|     1|    4|
|     1|    5|
|     2|    6|
|     4|    7|
|     4|    8|

我正在构建一个可视化的树层次结构,上面的数据将被格式化为:

|parent|child1|child2|child3
|------|------|------|------
|     0|     1|4     |     7
|     0|     1|4     |     8
|     0|     1|5     |
|     0|     2|6     |
|     0|     3|      |

现在我想修改这个查询,为每个没有孩子的父独立包含一行,所以上面的数据会变成:

|parent|child1|child2|child3
|------|------|------|------
|     0|      |      |
|     0|     1|      |
|     0|     1|     4|
|     0|     1|     4|     7
|     0|     1|     4|     8
|     0|     1|     5|
|     0|     2|      |
|     0|     2|     6|
|     0|     3|      |

为了获得第一个结果,我正在使用重复的左连接(使用上面的第一个数据示例)构建数据,据我所知,我无法通过递归来做到这一点,例如:

SELECT t1.child AS parent
       t2.child AS child1
       t3.child AS child2
       t4.child AS child3
FROM id_table t1

LEFT JOIN id_table t2
ON t1.child = t2.parent

LEFT JOIN id_table t3
ON t1.child = t3.parent

LEFT JOIN id_table t4
ON t1.child = t4.parent

WHERE t1.child = '0'

这得到了第二个示例,但我也缺少每个父母的记录,如第三个示例所示。

我认为这可能是一个简单的问题,我只是在语法上苦苦挣扎。 TIA 寻求帮助。

编辑:我对 SAS EG 中的类似实现有一个先前的问题:SQL - Recursive Tree Hierarchy with Record at Each Level,但那是 SAS SQL 实现受到更多限制 - 使用这种方法,我最终不得不在每个级别创建临时表然后联合最终结果,这是混乱的。试图找到更清洁的解决方案。

【问题讨论】:

  • 层次结构中有已知的层数吗?
  • @dnoeth 就本练习而言,16 个级别就足够了。

标签: sql parent-child teradata hierarchy


【解决方案1】:

GROUP BY ROLLUP 可用于创建这些额外的行:

SELECT DISTINCT
   t1.child AS Parent
  ,t2.child AS child1
  ,t3.child AS child2
  ,t4.child AS child3
  -- one more column for each additional level
FROM id_table t1

LEFT JOIN id_table t2
ON t1.child = t2.Parent

LEFT JOIN id_table t3
ON t2.child = t3.Parent

LEFT JOIN id_table t4
ON t3.child = t4.Parent

-- one additional join for each new level
WHERE t1.child = '0'

GROUP BY ROLLUP (t1.child,t2.child,t3.child,t4.child) 
HAVING t1.child IS NOT NULL

或递归查询遍历层次结构,构建路径,然后将其拆分为列:

WITH RECURSIVE cte AS
 ( -- traverse the hierarchy and built the path
   SELECT 1 AS lvl,
     ,child
     ,Cast(child AS VARCHAR(500)) AS Path -- must be large enough for concatenating all levels
   FROM id_table
   WHERE Parent IS NULL

   UNION ALL

   SELECT lvl+1
     ,t.child
     ,cte.Path || ',' || Trim(t.child)   
   FROM cte JOIN id_table AS t
   ON cte.child = t.Parent
   WHERE lvl < 20 -- just in case there's an endless loop
 ) 
SELECT 
   StrTok(Path, ',', 1) 
  ,StrTok(Path, ',', 2) 
  ,StrTok(Path, ',', 3) 
  ,StrTok(Path, ',', 4) 
  -- one additional StrTok for each new level
FROM cte

不知道哪个效率更高。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 2021-08-27
    • 2020-03-30
    • 2011-08-29
    • 1970-01-01
    • 2018-01-15
    相关资源
    最近更新 更多