junpet
junpet

Reputation: 85

Oracle query to migrate some columns into one

I have a table, which looks like this:

PK AA BB CC AA2 BB2 CC2 AA3 BB3 CC3 1 X Y Z D F G 2 Q W E 3 U I O P H K L R M

What I want to do with the query:

PK AAA BBB CCC 1 X Y Z 1 D F G 2 Q W E 3 U I O 3 P H K 3 L R M

Is this possible?

Upvotes: 1

Views: 92

Answers (3)

Kaushik Nayak
Kaushik Nayak

Reputation: 31648

You can use UNPIVOT

EDIT: There was no need of JOIN as in my original answer, thanks to @mathguy, I was able to correct it.

select pk,AAA,BBB,CCC FROM YOURTABLE 
UNPIVOT 
  ( (AAA,BBB,CCC) 
      FOR col in ( (aa, bb, cc), (aa2, bb2, cc2), (aa3, bb3, cc3) )
   ) 

DEMO

Upvotes: 3

user5683823
user5683823

Reputation:

Before the unpivot operator, unpivoting was done with a cross join to a small table (single column, as many rows as columns or groups of columns need to be unpivoted: in your case, six - or in the simplified example, three).

The reason for this approach - vs. the simple but inefficient union all approach - is that you only need to read the base table once.

Like this: ("table1" is the name of your base table)

select t.pk,
       case h.lvl  when 1 then aa
                   when 2 then aa2
                   when 3 then aa3 
            end as aa,
       case h.lvl  when 1 then bb
                   when 2 then bb2
                   when 3 then bb3
            end as bb,
       case h.lvl  when 1 then cc
                   when 2 then cc2
                   when 3 then cc3
            end as cc
from   table1 t
       cross join
       ( select level as lvl from dual connect by level <= 3 ) h
;

NOTE: This will also produce rows where aa, bb and cc are NULL (when, for example, aa3, bb3 and cc3 were null in the base table). These can be removed, if needed, by wrapping the cross join within an outer query and adding a where clause, for example: where aa is not null.

UNPIVOT

Here is how this can be done in Oracle 11.1 and higher. Groups of columns can be unpivoted in a single unpivot operation, like so:

select  pk, aa, bb, cc
from    table1
unpivot ( (aa, bb, cc) for rn in ( (aa, bb, cc), (aa2, bb2, cc2), (aa3, bb3, cc3) ) );

Upvotes: 1

krokodilko
krokodilko

Reputation: 36087

Use UNION ALL operator:

SELECT pk, aa As aaa,bb as bbb,cc as ccc 
FROM table1

UNION ALL

SELECT pk, aa2,bb2,cc2
FROM table1
WHERE aa2 IS NOT NULL

UNION ALL

SELECT pk, aa3,bb3,cc3
FROM table1
WHERE aa3 IS NOT NULL

Demo: http://sqlfiddle.com/#!4/6a7487/4

| PK | AAA | BBB | CCC |
|----|-----|-----|-----|
|  1 |   D |   F |   G |
|  1 |   X |   Y |   Z |
|  2 |   Q |   W |   E |
|  3 |   P |   H |   K |
|  3 |   L |   R |   M |
|  3 |   U |   I |   O |

Upvotes: 3

Related Questions