0

I have table like this below,

SNO     Name    Sales   Profit
1      John       50    20
2      Peter      60    0 
3      Mark       15    10
4      Nicolas      0  -10
5      Alex       70    20

I would like to convert this into below, (i.e sales and profit values should be combined to single column).

SNO     Name     Sales_Profit Values
1      John        Sales      50
1      John        profit     20
2      Peter       Sales      60
2      Peter       Profit      0

and So on.

Is there any way to handle this scenario without functions/procedures?

2 Answers 2

3

One method uses cross join:

select t.sno, s.name, sp.salesprofit,
       (case when sp.salesprofit = 'Sales' then sales else profit end) as values
from t cross join
     (select 'Profit' as salesprofit from dual union all
      select 'Sales' from dual
     ) sp;

The advantage of this approach over a union all is that it should only scan the table once.

Sign up to request clarification or add additional context in comments.

3 Comments

Surely much better than my answer (which I just deleted).
Thanks for this solution. Which one has better performance your query or one with union all ?
@ABR . . . In general, this will scan your table only once, which should be a performance gain. That said, scanning the table twice is really not a big deal, because it should already be cached for the second scan.
2

Oracle introduced the unpivot operator in version 11.1, exactly for this kind of problem. Illustrated below. I create the sample data in a with clause (not part of the query to answer your question; you should remove it, and use the actual table name). Note that values is an oracle reserved word, so it shouldn't be used as a column name; I use value instead. And there should be no forward slashes in column names; I replaced with an underscore.

with
  base_data (sno, name, sales, profit) as (
    select 1, 'John'   , 50,  20 from dual union all
    select 2, 'Peter'  , 60,   0 from dual union all 
    select 3, 'Mark'   , 15,  10 from dual union all
    select 4, 'Nicolas',  0, -10 from dual union all
    select 5, 'Alex'   , 70,  20 from dual
  )
select  *
from    base_data
unpivot include nulls 
    (value for sales_profit in (sales as 'Sales', profit as 'Profit'))
;

 SNO NAME    SALES_PROFIT  VALUE
---- ------- ------------ ------
   1 John    Sales            50
   1 John    Profit           20
   2 Peter   Sales            60
   2 Peter   Profit            0
   3 Mark    Sales            15
   3 Mark    Profit           10
   4 Nicolas Sales             0
   4 Nicolas Profit          -10
   5 Alex    Sales            70
   5 Alex    Profit           20

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.