繁体   English   中英

通过对行进行分组来更新Postgresql中的表

[英]Update table in Postgresql by grouping rows

我想通过基于某些条件将一些行分组(或合并)在一起来更新表。 我目前基本上有此表(我想按“ id_number”和“ date”对“ count”进行分组):

Table: foo
---------------------------------------
|  id_number  |   date      | count  |
---------------------------------------
| 1           |   2001      |    1   |
| 1           |   2001      |    2   |
| 1           |   2002      |    1   |
| 2           |   2001      |    6   |
| 2           |   2003      |    12  |
| 2           |   2003      |    2   |
---------------------------------------

我想得到这个:

Table: foo
 ---------------------------------------
|  id_number  |   date      | count  |
---------------------------------------
| 1           |   2001      |    3   |
| 1           |   2002      |    1   |
| 2           |   2001      |    6   |
| 2           |   2003      |    14  |
---------------------------------------

我知道我可以使用相关信息轻松创建一个新表。 但是,如何在不创建“临时”表的情况下修改现有表呢? (注意:我没有反对使用临时表的信息,我只是想看看是否可以通过这种方式进行操作)

如果要删除行,则可以添加一个主键(用于区分行)并使用两个句子,对于总和,使用UPDATE ;对于较少的行,使用DELETE

您可以执行以下操作:

create table foo (
  id        integer primary key,
  id_number integer,
  date      integer,
  count     integer
);

insert into foo values
  (1,    1      ,   2001      ,    1   ),
  (2,    1      ,   2001      ,    2   ),
  (3,    1      ,   2002      ,    1   ),
  (4,    2      ,   2001      ,    6   ),
  (5,    2      ,   2003      ,    12  ),
  (6,    2      ,   2003      ,    2   );

select * from foo;

update foo 
  set count = count_sum
  from (
      select id, id_number, date, 
             sum(count) over (partition by id_number, date) as count_sum
        from foo
        ) foo_added
  where foo.id_number = foo_added.id_number 
    and foo.date      = foo_added.date; 

delete from foo 
  using (
      select id, id_number, date, 
             row_number() over (partition by id_number, date order by id) as inner_order
        from foo
        ) foo_ranked
  where foo.id = foo_ranked.id
    and foo_ranked.inner_order <> 1;

select * from foo;

您可以在这里尝试: http : //rextester.com/PIL12447

仅一次更新

(但有触发器),您可以在count中设置一个NULL值,并在这种情况下触发DELETE

create table foo (
  id        integer primary key,
  id_number integer,
  date      integer,
  count     integer
);

create function delete_if_count_is_null() returns trigger 
  language plpgsql as
$BODY$
begin
  if new.count is null then
    delete from foo
      where id = new.id;
  end if;
  return new;
end;
$BODY$;

create trigger delete_if_count_is_null
  after update on foo
  for each row
  execute procedure delete_if_count_is_null();

insert into foo values
  (1,    1      ,   2001      ,    1   ),
  (2,    1      ,   2001      ,    2   ),
  (3,    1      ,   2002      ,    1   ),
  (4,    2      ,   2001      ,    6   ),
  (5,    2      ,   2003      ,    12  ),
  (6,    2      ,   2003      ,    2   );

select * from foo;

update foo 
  set count = case when inner_order = 1 then count_sum else null end
  from (
      select id, id_number, date, 
             sum(count) over (partition by id_number, date) as count_sum,
             row_number() over (partition by id_number, date order by id) as inner_order
        from foo
        ) foo_added
  where foo.id_number = foo_added.id_number 
    and foo.date      = foo_added.date
    and foo.id        = foo_added.id; 

select * from foo;

您可以在以下网址尝试使用: http : //rextester.com/MWPRG10961

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM