Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.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
Sql postgres-具有数组值的透视查询_Sql_Postgresql_Pivot - Fatal编程技术网

Sql postgres-具有数组值的透视查询

Sql postgres-具有数组值的透视查询,sql,postgresql,pivot,Sql,Postgresql,Pivot,假设我有这张桌子: Content +----+---------+ | id | title | +----+---------+ | 1 | lorem | +----|---------| 还有这个: Fields +----+------------+----------+-----------+ | id | id_content | name | value | +----+------------+----------+-----------+ | 1

假设我有这张桌子:

Content
+----+---------+
| id |  title  |
+----+---------+
| 1  | lorem   |
+----|---------|
还有这个:

Fields
+----+------------+----------+-----------+
| id | id_content |   name   |   value   |
+----+------------+----------+-----------+
| 1  |      1     | subtitle |   ipsum   |
+----+------------+----------+-----------|
| 2  |      1     |   tags   |   tag1    |
+----+------------+----------+-----------|
| 3  |      1     |   tags   |   tag2    |
+----+------------+----------+-----------|
| 4  |      1     |   tags   |   tag3    |
+----+------------+----------+-----------|
问题是:我想查询内容,将字段中的所有行转换为列,类似于:

+----+-------+----------+---------------------+
| id | title | subtitle |        tags         |
+----+-------+----------+---------------------+
|  1 | lorem | ipsum    | [tag1,tag2,tag3]    |
+----+-------+----------+---------------------|
此外,字幕和标签只是示例。我可以有我想要的任意多个字段,它们是数组还是非数组

但我还没有找到将重复的名称值转换为数组的方法,更不用说将subtitle转换为数组了。如果这是不可能的,字幕也可以变成一个数组,我可以在以后的代码中更改它,但我至少需要以某种方式对所有内容进行分组。有什么想法吗?

你可以使用array\u agg,例如

如果您也需要字幕,请使用自连接。我有一个子选择来处理没有任何标记的字幕,而不返回填充了NULL的数组,即{NULL}

有关详细信息,请参阅

如果您有权访问tablefunc模块,另一个选项是使用Houari指出的交叉表。您可以使用如下内容使其返回数组和非数组:

SELECT id_content, unnest(subtitle), tags
FROM crosstab('
    SELECT id_content, name, array_agg(value)
    FROM fields
    GROUP BY id_content, name
    ORDER BY 1, 2
') AS ct(id_content integer, subtitle text[], tags text[]);
但是,交叉表要求值始终以相同的顺序显示。例如,如果具有相同id_内容的第一个组没有字幕,而只有标签,则标签将不显示,并与字幕显示在同一列中

另请参见

如果副标题值是要分离的唯一常量,则可以执行以下操作:

SELECT * FROM crosstab
(
  'SELECT content.id,name,array_to_string(array_agg(value),'','')::character varying FROM content    inner join 
    (
    select * from fields where fields.name = ''subtitle''  
        union all  
    select * from fields where fields.name <> ''subtitle'' 
    ) fields_ordered 
   on fields_ordered.id_content = content.id   group by content.id,name'
)
AS
(
       id integer,
       content_name character varying,
       tags character varying
);

subtitle是唯一要分隔的特殊常量?@Houari,不,我可以在字段中任意多行。例如:字幕、描述、图像、标签数组、维度数组等。。这就是为什么它比看起来要复杂一点,字幕和标签只是一些例子。我可以有10个不同的字段,例如,4个是数组,6个是字符串。这就是我为什么要考虑pivot的原因。我将尝试将其与array_agg一起使用,它不是唯一的一个。我不能有我想要的那么多,有些是数组,有些不是。显然,我开始编辑我的答案,然后阅读你的答案。
SELECT id_content, unnest(subtitle), tags
FROM crosstab('
    SELECT id_content, name, array_agg(value)
    FROM fields
    GROUP BY id_content, name
    ORDER BY 1, 2
') AS ct(id_content integer, subtitle text[], tags text[]);
SELECT * FROM crosstab
(
  'SELECT content.id,name,array_to_string(array_agg(value),'','')::character varying FROM content    inner join 
    (
    select * from fields where fields.name = ''subtitle''  
        union all  
    select * from fields where fields.name <> ''subtitle'' 
    ) fields_ordered 
   on fields_ordered.id_content = content.id   group by content.id,name'
)
AS
(
       id integer,
       content_name character varying,
       tags character varying
);