如何在红移中加入行并将其转置为列

Posted

技术标签:

【中文标题】如何在红移中加入行并将其转置为列【英文标题】:How to join and transpose row to columns in redshift 【发布时间】:2021-12-09 00:14:15 【问题描述】:

我有关注table1,它的唯一键是type

type age
A     20
B     21
C     22

我有以下结果表。我想加入他们的行列

type score
A     10
A     20
A     30
B     40 
B     50

按照转置形式。

type  age  score score score
A     20    10    20    30
B     21    40    50    na
C     22    na    na    na

有什么方法可以实现吗?

select *
from table1
left join table2 usint(type)

没有转置行。 如果有人有意见请告诉我 谢谢

【问题讨论】:

Redshift 还是 Postgres?这是两个非常不同的数据库系统。 【参考方案1】:

如果您事先不知道每种类型的 score 值的数量,那么您需要一个完整的动态解决方案:

首先我们根据table2 中每个类型的score 值的最大数量创建一个复合类型new_type。然后使用此复合类型命名最终查询中的列。

CREATE OR REPLACE PROCEDURE new_type() LANGUAGE plpgsql AS
$$
DECLARE
  column_txt text ;
BEGIN
  SELECT string_agg(' score' || id || ' integer', ',')
   INTO column_txt
    FROM
       (  SELECT count(*) AS count
           FROM table2
          GROUP BY type
          ORDER BY 1 DESC
          LIMIT 1
       ) AS a
   CROSS JOIN LATERAL generate_series(1, a.count :: integer) AS id ;
     
  EXECUTE 'DROP TYPE IF EXISTS new_type' ;
  EXECUTE 'CREATE TYPE new_type AS (' || column_txt || ')' ;
END ;
$$ ;

CALL new_type() ;

那么这个查询将提供预期的结果:

SELECT c.type, c.age
     , (jsonb_populate_record( NULL :: new_type
                             , jsonb_object_agg('score' || c.id, c.score ORDER BY c.score)
                             )).*
  FROM 
     ( SELECT a.type, a.age, b.score, row_number() OVER (PARTITION BY a.type, a.age ORDER BY b.score) AS id
         FROM table1 AS a
         LEFT JOIN table2 AS b
           ON a.type = b.type
     ) AS c
 GROUP BY c.type, c.age
 ORDER BY c.type, c.age

测试结果在dbfiddle。

【讨论】:

以上是关于如何在红移中加入行并将其转置为列的主要内容,如果未能解决你的问题,请参考以下文章

如何在红移中加入复杂的条件

如何在红移光谱表中加载正确的数据?

红移。我们如何(动态地)将表从列转置为行?

如何在 MySQL 中将行数据转置为列

Oracle SQL Developer:如何使用 PIVOT 函数将行转置为列

在 Spark SQL (pyspark) 中将行转置为列