Home > other >  Unpivot postgres table having multiple columns
Unpivot postgres table having multiple columns

Time:01-05

I want to pivot a table having some columns like below.

ID week1 week2 week3 week4 week5 week6 week7
1 8 9 10 11 12 13 14
2 15 16 17 18 19 20 21
3 22 23 24 25 26 27 28

The desired output is -

ID week_number week_value
1 1 8
1 2 9
1 3 10
1 4 11
1 5 12
1 6 13
1 7 14
2 1 15
2 2 16
2 3 17
2 4 18
2 5 19
2 6 20
2 7 21
3 1 22
3 2 23
3 3 24
3 4 25
3 5 26
3 6 27
3 7 28

I tried using crosstab but couldn't get it working right. Below is my tried approach -

select * from crosstab('select ID,week1, week2,week3,week4,week5,week6,week7 order by ID') as table_name(ID, week_number, week_value);

Please can someone help as I don't have much experience in handling complex sql queries.

CodePudding user response:

This is actually the opposite of a pivot, also known as "unpivot" and can be done using a lateral cross join:

select t.id, x.*
from the_table t
  cross join lateral (
     values (1, week1), (2, week2), (3, week3), 
            (4, week4), (5, week5), (6, week6), 
            (7, week7)
  ) as x(week_number, week_value)
order by t.id, x.week_number  

CodePudding user response:

A quick alternative using JSONB that works for any number of colums provided that one of them is called id. Unrelated but the result looks alarmingly similar to the infamous EAV antipattern.

with t as (select to_jsonb(t) j from the_table t)
select j ->> 'id' id, 
       (jsonb_each_text(j - 'id')).*
from t;
id key value
1 week1 8
1 week2 9
1 week3 10
1 week4 11
1 week5 12
1 week6 13
1 week7 14
2 week1 15
2 week2 16
2 week3 17
2 week4 18
2 week5 19
2 week6 20
2 week7 21
3 week1 22
3 week2 23
3 week3 24
3 week4 25
3 week5 26
3 week6 27
3 week7 28

CodePudding user response:

Since you tagged the question with SparkSQL, here's a solution using stack function:

SELECT  ID,
        stack(7, '1', week1, '2', week2, '3', week3, '4', week4, '5', week5, '6', week6, '7', week7) as (week_number, week_value)
FROM    my_table

Applied to your example:

df = spark.createDataFrame([
    (1, 8, 9, 10, 11, 12, 13, 14),
    (2, 15, 16, 17, 18, 19, 20, 21),
    (3, 22, 23, 24, 25, 26, 27, 28)
], ["ID", "week1", "week2", "week3", "week4", "week5", "week6", "week7"])

df.createOrReplaceTempView("my_table")

spark.sql(above_query).show()

# --- ----------- ---------- 
#| ID|week_number|week_value|
# --- ----------- ---------- 
#|  1|          1|         8|
#|  1|          2|         9|
#|  1|          3|        10|
#|  1|          4|        11|
#|  1|          5|        12|
#|  1|          6|        13|
#|  1|          7|        14|
#|  2|          1|        15|
#|  2|          2|        16|
#|  2|          3|        17|
#|  2|          4|        18|
#|  2|          5|        19|
#|  2|          6|        20|
#|  2|          7|        21|
#|  3|          1|        22|
#|  3|          2|        23|
#|  3|          3|        24|
#|  3|          4|        25|
#|  3|          5|        26|
#|  3|          6|        27|
#|  3|          7|        28|
# --- ----------- ---------- 
  •  Tags:  
  • Related