Skip to Main Content

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question.

Asked: December 01, 2016 - 7:25 pm UTC

Last updated: December 02, 2016 - 1:43 pm UTC

Version: 11g

Viewed 1000+ times

You Asked

Hi Tom,

I have a Query:

SELECT A.SALES_ORDER_COMPANY as A_1, A.SALES_ORDER_NUMBER as A_2, A.SOURCE_SALES_ORDER_TYPE as A_3, A.SALES_LINE_NUMBER as A_4, A.SOURCE_SALESPERSON1_CODE as B, A.COMMISSION_AMT as C
FROM
SLS_PHI_BROKER_COMM_STG A
WHERE
A.SALES_ORDER_COMPANY='00810'
AND A.SALES_ORDER_NUMBER='1647081'
AND A.SOURCE_SALES_ORDER_TYPE='SE'
ORDER BY A.SALES_ORDER_COMPANY, A.SALES_ORDER_NUMBER, A.SOURCE_SALES_ORDER_TYPE, A.SALES_LINE_NUMBER,A.SOURCE_SALESPERSON1_CODE, A.COMMISSION_AMT;

The Output is :

A_1 A_2 A_3 A_4 B C
00810 1647081 SE 1 4175545 4693.989
00810 1647081 SE 1 4175596 6836.4
00810 1647081 SE 2 4175545 1173.497
00810 1647081 SE 2 4175596 1709.1

Now I want output like this (distinct A_1,A_2,A_3,A_4 in vertical and distinct B and C in horizontal) The number of columns (B and C) are fixed as B1,B2,B3,B4 and C1,C2,C3,C4 and depends number of distinct A_1,A_2,A_3,A_4 returned by query. If there is no value it should populate 0.
Hence I want the result like this :

A_1 A_2 A_3 A_4 B1 B2 B3 B4 C1 C2 C3 C4
00810 1647081 SE 1 4175545 4175596 0 0 4693.989 6836.4 0 0
00810 1647081 SE 2 4175545 4175596 0 0 1173.497 1709.1 0 0

I want plain SQL result for this (No PL/SQL).

Please Advice.

Thanks,
Vidhi

and Chris said...

Please! Wrap your statements and output in code tags. It's tricky to figure out which value belongs in which column otherwise...

The pivot operator will do what you want. But I'm not exactly sure what your rule is, so here's my best guess...

To use pivot, you need a column to pivot by. So you want to assign each row in the same group a number. The analytic row_number() will help you with this:

with rws as (
  select 00810 a1, 1647081 a2, 'SE' a3, 1 a4, 4175545 b, 4693.989 c  from dual union all
  select 00810, 1647081, 'SE', 1, 4175596, 6836.4 from dual union all
  select 00810, 1647081, 'SE', 2, 4175545, 1173.497 from dual union all
  select 00810, 1647081, 'SE', 2, 4175596, 1709.1 from dual
)
  select r.*,
         row_number() over (partition by a1, a2, a3, a4 order by rownum) rn
  from   rws r;

A1   A2         A3  A4  B          C          RN  
810  1,647,081  SE  1   4,175,545  4,693.989  1   
810  1,647,081  SE  1   4,175,596  6,836.4    2   
810  1,647,081  SE  2   4,175,545  1,173.497  1   
810  1,647,081  SE  2   4,175,596  1,709.1    2


You can then pivot by this calculated column. All the columns not listed in your pivot will form an implicit group by. So all the rows with the same A values will be on the same output row:

with rws as (
  select 00810 a1, 1647081 a2, 'SE' a3, 1 a4, 4175545 b, 4693.989 c  from dual union all
  select 00810, 1647081, 'SE', 1, 4175596, 6836.4 from dual union all
  select 00810, 1647081, 'SE', 2, 4175545, 1173.497 from dual union all
  select 00810, 1647081, 'SE', 2, 4175596, 1709.1 from dual
), grps as (
  select r.*,
         row_number() over (partition by a1, a2, a3, a4 order by rownum) rn
  from   rws r
)
  select * from grps
  pivot (sum(b) b, sum(c) c for rn in (1, 2, 3, 4))
  order  by 1, 2, 3, 4;

A1   A2         A3  A4  1_B        1_C        2_B        2_C      3_B  3_C  4_B  4_C  
810  1,647,081  SE  1   4,175,545  4,693.989  4,175,596  6,836.4                      
810  1,647,081  SE  2   4,175,545  1,173.497  4,175,596  1,709.1 


You then just need to rename and nvl your columns as needed.

If you want to know more about pivoting, read:

https://blogs.oracle.com/sql/entry/how_to_convert_rows_to

Is this answer out of date? If it is, please let us know via a Comment

More to Explore

Analytics

Analytic SQL got you confused? Check out Connor McDonald's complete video course.