簡體   English   中英

postgres-具有數組值的數據透視查詢

[英]postgres - pivot query with array values

假設我有這張桌子:

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]    |
+----+-------+----------+---------------------|

另外,字幕和標簽只是示例。 我可以根據需要設置任意多個字段,無論是否為數組。

但是我還沒有找到一種將重復的“名稱”值轉換為數組的方法,甚至還沒有將“字幕”轉換為數組的方法。 如果不可能的話,“字幕”也可以變成一個數組,我可以稍后在代碼上更改它,但是我至少需要以某種方式對所有內容進行分組。 有任何想法嗎?

您可以使用array_agg ,例如

SELECT id_content, array_agg(value)
FROM fields
WHERE name = 'tags'
GROUP BY id_content

如果您也需要字幕,請使用自連接。 我有一個subselect來應付沒有任何標簽的字幕,而不會返回填充有NULL的數組,即{NULL}

SELECT f1.id_content, f1.value, f2.value
FROM fields f1
LEFT JOIN (
    SELECT id_content, array_agg(value) AS value
    FROM fields
    WHERE name = 'tags'
    GROUP BY id_content
) f2 ON (f1.id_content = f2.id_content)
WHERE f1.name = 'subtitle';

有關詳細信息,請參見http://www.postgresql.org/docs/9.3/static/functions-aggregate.html

如果可以訪問tablefunc模塊,則另一種選擇是使用Houari指出的crosstab 您可以使用以下方法使其返回數組和非數組:

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[]);

但是, crosstab要求值始終以相同順序出現。 例如,如果第一組(具有相同的id_content )沒有字幕,而只有標簽,則標簽將被取消嵌套,並與字幕顯示在同一列中。

另請參見http://www.postgresql.org/docs/9.3/static/tablefunc.html

如果subtitle值是您要分隔的唯一“常量”,則可以執行以下操作:

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
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM