Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有动态列名和多个输入列的PostgreSQL交叉表 问题_Postgresql_Crosstab_Entity Attribute Value - Fatal编程技术网

具有动态列名和多个输入列的PostgreSQL交叉表 问题

具有动态列名和多个输入列的PostgreSQL交叉表 问题,postgresql,crosstab,entity-attribute-value,Postgresql,Crosstab,Entity Attribute Value,我有一个PostgreSQL 9.6数据库,其中的表是根据EAV模型设计的,具有不同类型的值。示例摘录如下所示: name |arrivalTime | boolValue | intValue | floatValue | stringValue ------+------------+-----------+----------+------------+------------ a1 | 10:00:00 | true | |

我有一个PostgreSQL 9.6数据库,其中的表是根据EAV模型设计的,具有不同类型的值。示例摘录如下所示:

 name |arrivalTime | boolValue | intValue | floatValue | stringValue
------+------------+-----------+----------+------------+------------
 a1   |  10:00:00  |   true    |          |            |
 c3   |  10:00:00  |           |   12     |            |
 d4   |  10:00:00  |           |          |            | hello
 e5   |  15:00:00  |           |          |    45.67   |
 c3   |  15:00:00  |           |   45     |            |
 b2   |  20:00:00  |           |          |    4.567   |
 a1   |  20:00:00  |   false   |          |            |
 d4   |  22:00:00  |           |          |            |  bye
 b2   |  22:00:00  |           |          |    12.34   |
arrivalTime |  a1   |  b2   |  c3   |  d4   |  e5
------------+-------+-------+-------+-------+-------
  10:00:00  | true  |       |  12   | hello |
  15:00:00  |       |       |  45   |       | 45.67
  20:00:00  | false | 4.567 |       |       |
  22:00:00  |       | 12.34 |       |  bye  |
空单元格表示数据库中的
null

现在我想得到一个透视表,新列是
arrivalTime
name
的内容。对于上面的示例,它应该如下所示:

 name |arrivalTime | boolValue | intValue | floatValue | stringValue
------+------------+-----------+----------+------------+------------
 a1   |  10:00:00  |   true    |          |            |
 c3   |  10:00:00  |           |   12     |            |
 d4   |  10:00:00  |           |          |            | hello
 e5   |  15:00:00  |           |          |    45.67   |
 c3   |  15:00:00  |           |   45     |            |
 b2   |  20:00:00  |           |          |    4.567   |
 a1   |  20:00:00  |   false   |          |            |
 d4   |  22:00:00  |           |          |            |  bye
 b2   |  22:00:00  |           |          |    12.34   |
arrivalTime |  a1   |  b2   |  c3   |  d4   |  e5
------------+-------+-------+-------+-------+-------
  10:00:00  | true  |       |  12   | hello |
  15:00:00  |       |       |  45   |       | 45.67
  20:00:00  | false | 4.567 |       |       |
  22:00:00  |       | 12.34 |       |  bye  |
作为检索此结果的查询输入,我得到一个与
名称
匹配的模式,以及指定
到达时间范围的开始和结束时间

原始表的属性:

  • “名称”列中的条目不稳定,即输入新名称 老名字也会定期消失
  • 名称
    到达时间
    的每个组合都是唯一的
  • 每个
    名称
    到达时间
    组合在其中一个值列中正好有一个条目
思想 我已经给了它一些考虑:

  • 我想得太多了,应该使用
    交叉表
    功能
  • 由于列是动态的,因此需要两个查询,如或中所述
  • 使用
    format()
    函数生成第一个查询可能是个好主意
示例表 以下是创建示例表的SQL代码:

CREATE TABLE IF NOT EXISTS playTable (
  name TEXT NOT NULL,
  arrivalTime TIME NOT NULL,
  floatValue REAL NULL,
  intValue INT NULL,
  boolValue BOOLEAN NULL,
  stringValue TEXT NULL,
  PRIMARY KEY (name, arrivalTime),
  CONSTRAINT single_value CHECK(
    (boolValue IS NOT NULL)::INT + 
    (intValue IS NOT NULL)::INT + 
    (floatValue IS NOT NULL)::INT +
    (stringValue IS NOT NULL)::INT = 1
  )
);
并插入以下值:

INSERT INTO playTable ( name, arrivalTime, boolValue ) VALUES ( 'a1', '10:00:00', true );
INSERT INTO playTable ( name, arrivalTime, intValue ) VALUES ( 'c3', '10:00:00', 12 );
INSERT INTO playTable ( name, arrivalTime, stringValue ) VALUES ( 'd4', '10:00:00', 'hello' );
INSERT INTO playTable ( name, arrivalTime, floatValue ) VALUES ( 'e5', '15:00:00', 45.67 );
INSERT INTO playTable ( name, arrivalTime, intValue ) VALUES ( 'c3', '15:00:00', 45 );
INSERT INTO playTable ( name, arrivalTime, floatValue ) VALUES ( 'b2', '20:00:00', 4.567 );
INSERT INTO playTable ( name, arrivalTime, boolValue ) VALUES ( 'a1', '20:00:00', false );
INSERT INTO playTable ( name, arrivalTime, stringValue ) VALUES ( 'd4', '22:00:00', 'bye' );
INSERT INTO playTable ( name, arrivalTime, floatValue ) VALUES ( 'b2', '22:00:00', 12.34 );
透视表,非动态 如果提供解决方案的起点,我想:

SELECT *
FROM crosstab(
    $ct$
        SELECT 
            arrivalTime, name, concat(boolValue, intValue, floatValue, stringValue)
        FROM playTable
        ORDER BY 1, 2
    $ct$,
    $ct$
        SELECT DISTINCT name 
        FROM playTable
        ORDER BY 1
    $ct$) 
AS ct("arrivalTime" time, "a1" BOOLEAN, "b2" REAL, "c3" INT, "d4" TEXT, "e5" REAL);
这个解决方案缺少的是动态方面。作为输入,提供了
名称的
模式和
到达时间的范围(即最小值和最大值)。这使得
作为ct(…)
的参数是动态的。

对最后四列使用
coalesce()
。要执行此操作,必须将列强制转换为
text

select *
from crosstab(
    $ct$
        select 
            arrivaltime, name, 
            coalesce(boolvalue::text, intvalue::text, floatvalue::text, stringvalue)
        from my_table
        order by 1, 2
    $ct$,
    $ct$
        select distinct name 
        from my_table
        order by 1
    $ct$) 
as ct("arrivalTime" time, "a1" text, "b2" text, "c3" text, "d4" text, "e5" text);

 arrivalTime |  a1   |  b2   | c3 |  d4   |  e5   
-------------+-------+-------+----+-------+-------
 10:00:00    | true  |       | 12 | hello | 
 15:00:00    |       |       | 45 |       | 45.67
 20:00:00    | false | 4.567 |    |       | 
 22:00:00    |       | 12.34 |    | bye   | 
(4 rows)

由于示例数据的格式,我使用了
arrivalTime
,将其更改为
timestamp

我使用了解决方案,并稍微扩展了我的问题。我将您的代码从使用
coalesce
更改为
concat
。这项工作很好,有重要的障碍,但我还没有完成:仍然缺少输入指定
名称
到达时间
范围的模式的能力。这使得
的参数成为ct(…)
dynamic.user711270您需要任何类型的编程语言,这些语言将为您生成SQL查询,并考虑输入模式。如果您使用的是SQL,则仅使用plpgsql创建此类动态查询。