Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining two rows from a table into one

I have a table where I've noticed that the unique constraint was set incorrectly, and duplicate rows have entered the table.

I set up this 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);

I'm trying to fix the table by coalescing values. Where a newer row exists, I want to take those values (It should have been an update instead of insert)

The final result I'd like is this, unique on real_id

3 | 1 | 'a1' | 'b1'
5 | 2 | 'a2' | 'b22'
6 | 3 | null | null

Basically I want the end result to look as if the first row was an insert and any following rows with the same real_id were partial updates

What kind of query can I use to create that final result set?

I'm using Postgres 9.4.

If what's needed to do this in sql is terrible or has very bad asymptotic performance I should be able to do it with linear complexity by pulling all rows to code (there's ~25000), and then doing the merge manually. It seems like it should be possible in sql though.

From a code perspective, it looks like a fold operation, so would a WITH RECURSIVE cte help me here?

like image 568
Daenyth Avatar asked Jul 23 '26 16:07

Daenyth


1 Answers

try this :

  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

If a and b are timestamp :

    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

Same for integer : split_part(string_agg(a::character varying ...,1)::integer

like image 97
Rémy Baron Avatar answered Jul 26 '26 11:07

Rémy Baron



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!