具有多列的 Unpivot postgres table

Unpivot postgres table having multiple columns

我想旋转一个 table 具有如下所示的一些列。

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

期望的输出是-

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

我尝试使用交叉表,但无法正常工作。以下是我尝试过的方法 -

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

请有人帮忙,因为我在处理复杂 sql 查询方面经验不多。

这实际上与枢轴相反,也称为“反枢轴”,可以使用横向交叉连接来完成:

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  

一种使用 JSONB 的快速替代方法,适用于任意数量的列,前提是其中一个列称为 id。无关,但结果看起来与臭名昭著的 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

由于您使用 SparkSQL 标记了问题,这里有一个使用 stack 函数的解决方案。应用于您的示例:

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("""
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
""").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|
#+---+-----------+----------+