从变量表数据创建Postgres表

时间:2014-04-15 17:49:12

标签: sql postgresql transform transpose database-table

我有一个Postgres数据表,如下所示(例如):

╔════╦═══════════╦════════════╗
║ ID ║ FieldName ║ FieldValue ║
╠════╬═══════════╬════════════╣
║ 66 ║ PO#       ║   11111111 ║
║ 66 ║ Zip       ║      01810 ║
║ 66 ║ Badge     ║   22222222 ║
║ 67 ║ PO#       ║    7777777 ║
║ 67 ║ Zip       ║      02144 ║
║ 67 ║ Badge     ║   99999999 ║
╚════╩═══════════╩════════════╝

我的问题是如何将此表转换为如下所示的新表:

╔════╦══════════╦════════╦══════════╗
║ ID ║  Field1  ║ Field2 ║  Field3  ║
╠════╬══════════╬════════╬══════════╣
║ 66 ║ 11111111 ║  01810 ║ 22222222 ║
║ 66 ║  7777777 ║  02144 ║ 99999999 ║
╚════╩══════════╩════════╩══════════╝

我需要完全使用Postgres语法完成。理想情况下,我还能够动态地计算出有多少字段,但这是次要的需求。目前,假设有三个字段,我需要将它们转换为名为Field#的新列。

1 个答案:

答案 0 :(得分:1)

使用tablefunc模块中的crosstab()函数。详细说明和链接(请先阅读!):
PostgreSQL Crosstab Query

您的查询可能如下所示:

SELECT *
FROM   crosstab(
         'SELECT "ID", "FieldName", "FieldValue"
          FROM   tbl
          ORDER  BY 1'

         ,$$VALUES ('PO#'::text), ('Zip'), ('Badge')$$
       ) AS ct ("Section" text, "Field1" int, "Field2" int, "Field3" int);

dynamically figure out how many fields there were,您必须动态构建上述语句。 SQL要求知道返回类型。在这个相关问题下的更多细节:
Dynamic alternative to pivot with CASE and GROUP BY