将表中的两行合并为一行

时间:2016-06-29 15:17:29

标签: postgresql unique-constraint

我有一张表格,我注意到唯一约束设置不正确,重复的行已进入表格。

我设置了这个sqlfiddle:http://sqlfiddle.com/#!15/c4a5d/1/0

create table foo (
bad_id INT NOT NULL,
real_id INT NOT NULL,
a TEXT,
b TEXT
);

insert into foo values
(1, 1, 'a1', null),
(2, 1, null, 'b1'),
(3, 1, null, null),
(4, 2, 'a22', 'b2'),
(5, 2, 'a2', 'b22'),
(6, 3, null, null);

我试图通过合并值来修复表格。如果存在较新的行,我想获取这些值(它应该是更新而不是插入)

我喜欢的最终结果是real_id

上的唯一结果
3 | 1 | 'a1' | 'b1'
5 | 2 | 'a2' | 'b22'
6 | 3 | null | null

基本上我希望最终结果看起来好像第一行是插入,而后面的任何一行real_id都是部分更新

我可以使用哪种查询来创建最终结果集?

我使用的是Postgres 9.4。

如果在sql中需要做什么是非常糟糕的或者具有非常糟糕的渐近性能,我应该能够通过将所有行拉到代码来实现线性复杂性(那里~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~然后手动进行合并。看起来它应该可以在sql中使用。

从代码的角度来看,它看起来像fold操作,所以WITH RECURSIVE cte会帮助我吗?

1 个答案:

答案 0 :(得分:2)

试试这个:

  select max(bad_id),
    split_part(string_agg(a,'__SPLITER__' order by bad_id DESC),'__SPLITER__',1)
    ,split_part(string_agg(b,'__SPLITER__' order by bad_id DESC),'__SPLITER__',1)  
  from foo group by real_id

如果a和b是时间戳:

    select max(bad_id),
        split_part(string_agg(a::character varying,'__SPLITER__' order by bad_id DESC),'__SPLITER__',1)::timestamp,
        split_part(string_agg(b::character varying,'__SPLITER__' order by bad_id DESC),'__SPLITER__',1)::timestamp  
    from foo group by real_id

整数相同:split_part(string_agg(a :: character varying ...,1):: integer