How to transpose data in postgresql

Suppose you have a table  tbl_sales as below:

Country Category date sales
USA FOOD 12/30/2017 1254
USA FOOD 09/30/2017 1154
USA FOOD 06/30/2017 1200
USA FOOD 03/30/2017 1500
USA TOYS 12/30/2017 1478
USA TOYS 09/30/2017 5684
USA TOYS 06/30/2017 4859
USA TOYS 03/30/2017 1548

and you have to transpose date into columns of 4 quarters.

First create rank function to distinct the quarters from date:

select row_number() over (partition by country, category, sales,
date_part('year', date) order by country, category asc, sales, date desc ) as row_num,* from tbl_sales 
above query will add row_num column as shown below:


row_num country category date sales
1 USA FOOD 12/30/2017 1254
2 USA FOOD 09/30/2017 1154
3 USA FOOD 06/30/2017 1200
4 USA FOOD 03/30/2017 1500
1 USA TOYS 12/30/2017 1478
2 USA TOYS 09/30/2017 5684
3 USA TOYS 06/30/2017 4859






On top of above query use case statement to create 4 quarter's columns


select e.country, e.category,  e.sales, e.date,
case when row_num= 1 then company_actual end as Q1,
case when row_num= 2 then company_actual end as Q2,
case when row_num= 3 then company_actual end as Q3,
case when row_num= 4 then company_actual end as Q4 from 
select row_number() over (partition by country, category, sales, date_part('year', date) order by country, category asc, sales, date desc ) as row_num , * from tbl_sales 

) e order by 1,2


above query will generate below output:

row_num country category date sales Q1 Q2 Q3 Q4
1 USA FOOD 12/30/2017 1254 1254
2 USA FOOD 09/30/2017 1154 1154
3 USA FOOD 06/30/2017 1200 1200
4 USA FOOD 03/30/2017 1500 1500
1 USA TOYS 12/30/2017 1478 1478
2 USA TOYS 09/30/2017 5684 5684
3 USA TOYS 06/30/2017 4859 4859
4 USA TOYS 03/30/2017 1548 1548



Now we just have to use group by query to get final result:

select country, category,
sum(Q1) Q1,
sum(Q2) Q2,
sum(Q3) Q3,
sum(Q4) Q4   from
(
select e.country, e.category,  e.sales,
case when row_num= 1 then company_actual end as Q1,
case when row_num= 2 then company_actual end as Q2,
case when row_num= 3 then company_actual end as Q3,
case when row_num= 4 then company_actual end as Q4 from
select row_number() over (partition by country, category, sales, date_part('year', date) order by country, category asc, sales, date desc ) as row_num,
* from tbl_sales  ) e
order by 1,2 ) B
group by 1,2 order by  1,2


Here we get transposed output:

country category Q1 Q2 Q3 Q4
USA FOOD 1254 1154 1200 1500
USA TOYS 1478 5684 4859 1548



Comments

Popular Posts