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

时间:2017-09-08 15:40:20

标签: sql postgresql group-by

我想通过根据特定条件将某些行分组(或组合)来更新表。我目前基本上都有这个表格(我希望按照' 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  |
---------------------------------------

我知道我可以轻松地创建一个包含相关信息的新表格。但是如何修改这样的现有表而不使用" temp"表? (注意:我没有反对使用临时表,我只是想知道我是否可以这样做)

1 个答案:

答案 0 :(得分:0)

如果要删除行,可以添加主键(用于区分行)并使用两个句子,总和为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

只有一个UPDATE

(但是使用触发器)您可以在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

中试用