如何更新同一个表中的分层数据

时间:2015-11-26 11:13:38

标签: postgresql sql-update hierarchical

我有两张桌子。第一个表包含按年份和territory_id的一些数据更改。

territory_id      year  count_sth
430000000         2015  130
431000000         2015  15
433200000         2015  75
433600000         2015  40
431000000         2014  13
433200000         2014  20
...

第二个表包含parent-id形式的parent-id之间的关系。

territory_id      parent_id     desc_ru
430000000         0             'abc'
431000000         430000000     'sdf'    
433200000         430000000     'jkl'
433210000         433200000     'bnm'
...

我想将列count_sth(table1)的值设置为按年份划分的子组的值的总和。它应该自动更新。每当我们更新count_sth时,其中count_sth为某个地区的父级的territory_id的值将等于其子项的值count_sth的总和。 怎么做? 我尝试使用函数返回触发器来更新这个(table1)表。

CREATE OR REPLACE FUNCTION table__byyear()
RETURNS trigger AS
$func$
  BEGIN

UPDATE table__byyear f
SET    count_sth= A.a1
    from (select b.year, b.sum(count_sth) as a1, t.parent_id
          from table__byyear b join admterr t
          on b.territory_id = t.territory_id 
             GROUP by b.year, t.parent_id) A
where f.territory_id = A.parent_id and f.year = A.year
AND   count_sth IS DISTINCT FROM A.a1;

RETURN NULL;
END
$func$  LANGUAGE plpgsql;


CREATE TRIGGER table__byyear_terr
BEFORE INSERT OR UPDATE ON table__byyear 
FOR EACH ROW EXECUTE PROCEDURE table__byyear();

但是在这里,这个UPDATE触发器在同一个表上运行另一个UPDATE,它将再次触发触发器,因此我们得到无限递归。 指出我正确的方向。

1 个答案:

答案 0 :(得分:0)

您可以使用以下语句一次更新行和所有父行:

with recursive hier as (
  -- a row
  select t.territory_id, 
         t.parent_id,
         b.year
  from   table__byyear b,
         admterr t
  where  t.territory_id = 433210000 --<< change me
  and    b.year = 2015              --<< change me
  and    t.territory_id = b.territory_id
  union all
  -- parent rows
  select t.territory_id,
         t.parent_id,
         prev.year
  from   hier prev,
         admterr t
  where  t.territory_id = prev.parent_id
)
update table__byyear
set    count_sth = count_sth + 100 --<< change me
where  (territory_id, year) in (select territory_id, year from hier);

鉴于此声明,您可能想要创建一个函数......

create function update_hier(
  territory_id integer,
  year integer,
  delta numeric
)
returns void
as $$
  with ...
  update table__byyear
  set    count_sth = count_sth + $3
  where  (territory_id, year) in (select territory_id, year from hier);
$$ language sql;

...甚至创建一个带有反向更新触发器的视图来调用此函数。