Postgres - 将行转置为列

时间:2014-04-14 12:35:59

标签: sql database postgresql crosstab transpose

我有下表,它为每个用户提供了多个电子邮件地址。

enter image description here

我需要将其展平为用户查询的列。根据创建日期向我提供“最新”3个电子邮件地址。

user.name | user.id | email1          | email2           | email3**

Mary      | 123     | mary@gmail.com  | mary@yahoo.co.uk | mary@test.com

Joe       | 345     | joe@gmail.com   | [NULL]           | [NULL]

2 个答案:

答案 0 :(得分:42)

使用tablefunc模块中的crosstab()

SELECT * FROM crosstab(
   $$SELECT user_id, user_name, rn, email_address
     FROM  (
        SELECT u.user_id, u.user_name, e.email_address
             , row_number() OVER (PARTITION BY u.user_id
                            ORDER BY e.creation_date DESC NULLS LAST) AS rn
        FROM   usr u
        LEFT   JOIN email_tbl e USING (user_id)
        ) sub
     WHERE  rn < 4
     ORDER  BY user_id
   $$
  , 'VALUES (1),(2),(3)'
   ) AS t (user_id int, user_name text, email1 text, email2 text, email3 text);

我使用美元引用作为第一个参数,没有特殊含义。如果您必须在查询字符串中转义单引号(这是常见情况),这很方便:

详细说明和说明:

特别是对于&#34;额外的列&#34;:

这里的特殊困难是:

  • 缺少关键名称 - &GT;我们在子查询中用row_number()替换。

  • 不同数量的电子邮件。
    - &GT;我们限制到最大值。外部SELECT中的三个  并使用crosstab()和两个参数,提供可能的键列表。

注意NULLS LAST in the ORDER BY

答案 1 :(得分:9)

如果其他人发现了这个问题,并且需要一个动态解决方案,你有一个未定义的列数要转置,而不是3,你可以在这里找到一个很好的解决方案:https://github.com/jumpstarter-io/colpivot