使用 parents 和 children 的记录创建 parent 和 child 层次结构
Make parent and child hierarchy with records for parents as well as children
我有一个 parent-child 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| |
现在我想修改此查询以在没有 child 的情况下为每个 parent 独立包含一行,因此以上数据将变为:
|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'
这是我的第二个示例,但我也缺少每个 parent 的记录,如第三个示例所示。
我想这可能是一个简单的问题,我只是在为语法苦苦挣扎。 TIA 寻求任何帮助。
编辑:我之前有一个关于 SAS EG 中类似实现的问题:SQL - Recursive Tree Hierarchy with Record at Each Level,但那是 SAS SQL 实现,它受到更多限制 - 我最终采用了这种方法只需在每个级别创建临时表,然后合并最终结果,这很混乱。试图找到更清洁的解决方案。
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
不知道哪个效率更高
我有一个 parent-child 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| |
现在我想修改此查询以在没有 child 的情况下为每个 parent 独立包含一行,因此以上数据将变为:
|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'
这是我的第二个示例,但我也缺少每个 parent 的记录,如第三个示例所示。
我想这可能是一个简单的问题,我只是在为语法苦苦挣扎。 TIA 寻求任何帮助。
编辑:我之前有一个关于 SAS EG 中类似实现的问题:SQL - Recursive Tree Hierarchy with Record at Each Level,但那是 SAS SQL 实现,它受到更多限制 - 我最终采用了这种方法只需在每个级别创建临时表,然后合并最终结果,这很混乱。试图找到更清洁的解决方案。
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
不知道哪个效率更高