PostgreSQL行到列

use*_*871 2 sql postgresql row crosstab

我正在尝试创建一个动态系统,允许用户从Excel导入数据列表,所以我需要有动态列,例如:

custom_columns_table
id   list_id  data_type       column_name  data              ....
1    1        VARCHAR(255)    email        jhon@example.com  ....
2    1        VARCHAR(255)    name         Jhon              ....

list_table
id
1
Run Code Online (Sandbox Code Playgroud)

我需要这样的结果:

id email             name  ....
1  jhon@example.com  Jhon  ....
Run Code Online (Sandbox Code Playgroud)

我找到了一些使用交叉表的例子,但我不知道它是否适用于这种情况.

有谁知道我该怎么做?

Erw*_*ter 9

首先,crosstab()函数系列没有安装在标准的PostgreSQL中.您需要为此安装扩展tablefunc.在PostgreSQL 9.1中你只需:

CREATE EXTENSION tablefunc;
Run Code Online (Sandbox Code Playgroud)

对于旧版本,请查看此相关答案.

询问

查询可能如下所示:

SELECT *
FROM   crosstab (
        'SELECT l.id
               ,c.column_name
               ,c.data
         FROM   custom_columns_table c
         JOIN   list_table l ON l.id = c.list_id
         ORDER  BY 1',

        'SELECT DISTINCT column_name
         FROM   custom_columns_table
         ORDER  BY 1')
AS tbl (
    id integer
   ,email text
   ,name text
   );
Run Code Online (Sandbox Code Playgroud)

我使用crosstab()带有两个参数的形式,因为这允许缺少属性.就像,当一个人没有电子邮件时.然后,这种形式将返回NULLemail列.详细说明:

功能

或者创建一个函数,这样您就不必为每个调用提供列定义列表:

CREATE OR REPLACE FUNCTION f_mycross(text, text)
  RETURNS TABLE (
    id integer
   ,email text
   ,name text)
  AS '$libdir/tablefunc','crosstab_hash' LANGUAGE C STABLE STRICT;
Run Code Online (Sandbox Code Playgroud)

呼叫:

SELECT * FROM f_mycross(
       'SELECT l.id
              ,c.column_name
              ,c.data
        FROM   custom_columns_table c
        JOIN   list_table l ON l.id = c.list_id
        ORDER  BY 1',

       'SELECT DISTINCT column_name
        FROM   custom_columns_table
        ORDER  BY 1')
Run Code Online (Sandbox Code Playgroud)