我有一个与此类似的表:

CREATE TABLE example (
  id integer primary key,
  name char(200),
  parentid integer,
  value integer);

我可以使用parentid 字段将数据排列成树结构。

现在这是我无法解决的一点。给定一个parentid,是否可以编写一条SQL语句来累加该parentid下的所有值字段并向下递归树的分支?

更新: 我使用的是 posgreSQL,所以我无法使用精美的 MS-SQL 功能。无论如何,我希望将其视为一个通用的 SQL 问题。

顺便说一句,我很高兴在提问后 15 分钟内得到了 6 个答案!堆栈溢出!

有帮助吗?

解决方案

有几种方法可以在 PostgreSQL 中满足您的需要。

像这样的东西:

create or replace function example_subtree (integer)
returns setof example as
'declare results record;
         child record;
 begin
  select into results * from example where parent_id = $1;
  if found then
    return next results;
    for child in select id from example
                  where parent_id = $1
      loop
        for temp in select * from example_subtree(child.id)
        loop
          return next temp;
        end loop;
      end loop;
  end if;
  return null;
end;' language 'plpgsql';

select sum(value) as value_sum
  from example_subtree(1234);

其他提示

以下是使用公用表表达式的示例脚本:

with recursive sumthis(id, val) as (
    select id, value
    from example
    where id = :selectedid
    union all
    select C.id, C.value
    from sumthis P
    inner join example C on P.id = C.parentid
)
select sum(val) from sumthis

上面的脚本创建了一个名为的“虚拟”表 sumthis 有列的 idval. 。它被定义为两个选择合并的结果 union all.

第一的 select 得到根(where id = :selectedid).

第二 select 迭代地跟踪先前结果的子级,直到没有任何内容可返回。

然后可以像普通表一样处理最终结果。在这种情况下,val 列被求和。

从 8.4 版本开始,PostgreSQL 递归查询支持 对于使用 SQL 标准的公用表表达式 WITH 句法。

如果您想要一个适用于任何 ANSI 的便携式解决方案 SQL-92 RDBMS,您需要向表中添加新列。

乔·塞尔科 (Joe Celko) 是该书的原作者 嵌套集 在 SQL 中存储层次结构的方法。你可以谷歌 “嵌套集”层次结构 以了解更多有关背景的信息。

或者你可以将parentid重命名为 左侧 并添加一个 右ID.

这是我尝试总结嵌套集的尝试,但由于我不是 Joe Celko,所以它会严重不足:SQL 是一种基于集合的语言,邻接模型(存储父 ID)不是层次结构的基于集合的表示。因此,不存在纯粹的基于集合的方法来查询邻接模式。

然而, 近年来,大多数主要平台都推出了扩展来处理这个精确的问题。因此,如果有人回复 Postgres 特定的解决方案,请务必使用它。

进行递归查询的标准方法 SQL 是递归的 CTE. PostgreSQL 支持他们,因为 8.4.

在早期版本中,您可以编写递归集合返回函数:

CREATE FUNCTION fn_hierarchy (parent INT)
RETURNS SETOF example
AS
$$
        SELECT  example
        FROM    example
        WHERE   id = $1
        UNION ALL
        SELECT  fn_hierarchy(id)
        FROM    example
        WHERE   parentid = $1
$$
LANGUAGE 'sql';

SELECT  *
FROM    fn_hierarchy(1)

参见这篇文章:

如果您使用 SQL Server 2005,那么有一种非常酷的方法可以使用公用表表达式来执行此操作。

它消除了创建临时表的所有繁琐工作,并且基本上允许您仅使用WITH和UNION来完成这一切。

这是一个很好的教程:

http://searchwindevelopment.techtarget.com/tip/0,289483,sid8_gci1278207,00.html

用一个 公用表表达式.

可能想要表明这仅限于 SQL Server 2005 或更高版本。 戴尔·拉根

这是一篇文章 没有公共表表达式的 SqlTeam 递归。

以下代码可以编译并测试正常。

create or replace function subtree (bigint)
returns setof example as $$
declare
    results record;
    entry   record;
    recs    record;
begin
    select into results * from example where parent = $1;
    if found then
        for entry in select child from example where parent = $1 and child  parent loop
            for recs in select * from subtree(entry.child) loop
                return next recs;
            end loop;
        end loop;
    end if;
    return next results;
end;
$$ language 'plpgsql';

在我的例子中需要条件“child <>parent”,因为节点指向它们自己。

玩得开心 :)

Oracle 有“START WITH”和“CONNECT BY”

select 
    lpad(' ',2*(level-1)) || to_char(child) s

from 
    test_connect_by 

start with parent is null
connect by prior child = parent;

http://www.adp-gmbh.ch/ora/sql/connect_by.html

顺便说一句,尽管这个问题已经得到很好的回答,但应该指出的是,如果我们将其视为:

通用 SQL 问题

那么 SQL 实现相当简单,因为 SQL'99 允许规范中的线性递归(尽管我相信没有 RDBMS 完全实现该标准)通过 WITH RECURSIVE 陈述。所以从理论角度来看我们现在就可以做到这一点。

这些示例对我来说都不起作用,所以我像这样修复了它:

declare
    results record;
    entry   record;
    recs    record;
begin
    for results in select * from project where pid = $1 loop
        return next results;
        for recs in select * from project_subtree(results.id) loop
            return next recs;
        end loop;
    end loop;
    return;
end;

这是 SQL Server 吗?您不能编写一个 TSQL 存储过程来循环并将结果合并在一起吗?

我也很感兴趣是否有一种仅 SQL 的方法可以做到这一点。从我在地理数据库课上的记忆来看,应该有。

我认为在 SQL 2008 中更容易 层次结构ID

如果您需要存储任意图形,而不仅仅是层次结构,您可以将 Postgres 推到一边并尝试图形数据库,例如 快板:

图形数据库中的所有内容都存储为三元组(源节点、边、目标节点),它为操作图形结构并使用类似 SQL 的语言查询它提供了一流的支持。

它与 Hibernate 或 Django ORM 之类的东西集成得不好,但如果您认真对待图形结构(不仅仅是像 Nested Set 模型给您的层次结构),请检查一下。

我还相信 Oracle 最终在其最新产品中添加了对真实图的支持,但我很惊讶它花了这么长时间,很多问题都可以从这个模型中受益。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top