Reputation: 2434
I have a table with a collection of nullable columns. What I need to do is 'shift' these columns "left" so that column 1 contains the first non-null value, column 2 contains the second non-null value, etc.
e.g.
This:
<null>, <null>, foo, bar, baz, buz
<null>, <null>, <null>, <null>, foo, bar
<null>, <null>, <null>, foo, bar, baz
needs to become this:
foo, bar, baz, buz, <null>, <null>
foo, bar, <null>, <null>, <null>, <null>
foo, bar, baz, <null>, <null>, <null>
I can be certain that the data contains 0 or more columns followed by 1 or more non-null columns.
I can imagine a way to acheive this with gratuitous use CASE statements, but I'd rather not create such an abomination.
Anyone have a clue how to get this done easily?
Upvotes: 0
Views: 465
Reputation: 1269503
I think the simplest way is an unpivot/pivot. You can do this as:
select id,
max(case when seqnum = 1 then col end) as col1,
max(case when seqnum = 2 then col end) as col2,
max(case when seqnum = 3 then col end) as col3,
max(case when seqnum = 4 then col end) as col4,
max(case when seqnum = 5 then col end) as col5,
max(case when seqnum = 6 then col end) as col6
from (select t.*, row_number() over (partition by id order by pos) as seqnum
from ((select id, col1 as col, 1 as pos from t) union all
(select id, col2 as col, 2 as pos from t) union all
(select id, col3 as col, 3 as pos from t) union all
(select id, col4 as col, 4 as pos from t) union all
(select id, col5 as col, 5 as pos from t) union all
(select id, col6 as col, 6 as pos from t)
) t
where col is not null
) t
group by id;
Because Redshift is a columnar database, the union all
should be about as efficient as any other way of unpivoting the data.
Upvotes: 1