Sql 规范化逻辑层次结构的度量和

Sql 规范化逻辑层次结构的度量和,sql,recursion,teradata,Sql,Recursion,Teradata,假设下表1描述了父子关系和度量: Parent | Child | Metric (of a child) ------------------------------------ name0 | name1 | a name0 | name2 | b name1 | name3 | c name2 | name4 | d name2 | name5 | e name3 | name6 | f 特征: 1) 孩子总是有一个且只有一个父母 2) 父级可以有多个子级(name2

假设下表1描述了父子关系和度量:

Parent | Child | Metric (of a child)
------------------------------------
name0 | name1 | a  
name0 | name2 | b  
name1 | name3 | c  
name2 | name4 | d  
name2 | name5 | e  
name3 | name6 | f
特征:
1) 孩子总是有一个且只有一个父母
2) 父级可以有多个子级(name2将name4和name5作为子级)
3) “层次”中的级别数和任何给定父级的子级数是任意的,且不相互依赖

我需要一个SQL请求,该请求将返回结果集,其中包含每个名称及其所有子体的度量值之和,下至底层再加上自身,因此对于这个示例表,结果将是(仔细查看name1):

(name0不相关,可以排除)

它应该是ANSI或Teradata SQL

我得到了一个递归查询,它可以返回给定名称的所有子代的和(度量):

WITH RECURSIVE temp_table (Child, metric) AS
(  
   SELECT root.Child, root.metric  
   FROM table1 root  
   WHERE root.Child = 'name1'  
   UNION ALL  
   SELECT indirect.Child, indirect.metric  
   FROM temp_table direct, table1 indirect  
   WHERE direct.Child = indirect.Parent
)  
SELECT SUM(metric) FROM temp_table;  
有没有办法把这个查询转换成一个以name为参数并返回这个和的函数,这样就可以这样调用它

SELECT Sum_Of_Descendants (Child) FROM Table1;

任何关于如何从不同角度处理这一问题的建议都将受到赞赏,因为即使上述方法是可实现的,它的性能也会很差——读取度量的迭代次数会很多(在本例中,值f将被读取3次)。理想情况下,查询应该只读取每个名称的度量值一次。

编辑:此答案适用于支持公共表表达式的SQL Server 2005及更高版本。当我第一次回答这个问题时,我没有注意到
teradata
标记。希望这个答案仍然相关,因为语法似乎几乎相同

这可以在SQL Server中通过将每个级别的层次结构扩展为

with recursive temp_table (RootValue, Child, Metric)
as 
(select
    root.Child, root.Child, root.Metric
from table1 root
union all
select
    direct.RootValue, indirect.Child, indirect.Metric
from temp_table direct join table1 indirect on indirect.Parent = direct.Child
)
select
    RootValue, SUM(Metric)
from temp_table
group by RootValue;
(公共表表达式)CTE定义除了Child和Metric之外还有一个RootValue列。 CTE递归地关联给定根值的子值和度量值


给定这个CTE,所需的输出只是在RootValue列上聚合的问题

您是否考虑过在查询时指定子级的递归视图定义?@RobPaller:我认为这是个好主意;把它作为答案贴出来,这样我就可以投票了!与递归查询相比,这有什么优势?我仍然需要在视图定义中硬编码初始的“root”名称,对吗?您现在可以发布递归查询吗?它可能像添加where子句一样简单。您可以使用其他工具进行递归求和吗?Teradata与其说是关系数据管理工具,不如说是仓库工具。谢谢。我花了一些时间来弄清楚它是如何工作的——我看到的所有示例都有硬编码的初始值,所以我认为这是递归的必要条件。校长在这里解释得很清楚-
with recursive temp_table (RootValue, Child, Metric)
as 
(select
    root.Child, root.Child, root.Metric
from table1 root
union all
select
    direct.RootValue, indirect.Child, indirect.Metric
from temp_table direct join table1 indirect on indirect.Parent = direct.Child
)
select
    RootValue, SUM(Metric)
from temp_table
group by RootValue;