按对象键将SQL JSONB数组转换为列

时间:2015-11-24 19:20:33

标签: sql arrays postgresql jsonb

我的表格结构如下:

CREATE TABLE artists (artist TEXT UNIQUE, facts JSONB);

INSERT INTO artists (artist, facts) 
  VALUES ('adele', '[{"type": "full_name", "value": "Adele Laurie"}, {"type": "age", "value": "25"}]');

INSERT INTO artists (artist, facts) 
  VALUES ('taylor', '[{"type": "age", "value": "25"}, {"type": "last_album", "value": "1989"}]');

有一定数量的事实“类型”,但不是每个艺术家都会有各自的事实。如何为每个事实类型选择包含列的结果,为缺少的事实名称选择null?

期望的输出:

| artist |  full_name    | age  | last_album |
|--------|---------------|------|------------|
| adele  | Adele Laurie  | 25   | null       |
| taylor | null          | 25   | 1989       |

2 个答案:

答案 0 :(得分:1)

你可以这样做:

select a.artist, 
     max(case when b.value->>'type' = 'full_name' 
         then b.value->>'value' 
         else b.value->>'full_name' end) as full_name,
     max(case when b.value->>'type' = 'age' 
         then b.value->>'value' 
         else b.value->>'age' end) as age,
     max(case when b.value->>'type' = 'last_album' 
         then b.value->>'value' 
         else b.value->>'last_album' end) as last_album
from artists a, 
     json_array_elements(a.facts) b
group by a.artist
order by a.artist

请在此处查看:http://sqlfiddle.com/#!15/e376b/2

在小提琴中我创建了JSON字段,因为JSONB类型

不可用

如果您需要添加更多类型,只需将其添加为其他类型的案例条件。我想你可以从这里弄明白:)

修改

即使您更改了格式,此查询也可以解决您的问题。刚刚编辑了小提琴。请在此处查看:http://sqlfiddle.com/#!15/1c2b6/2

唯一的区别是你并不真的需要案件陈述的其他内容。

这是没有else语句的查询

select a.artist, 
     max(case when b.value->>'type' = 'full_name' 
         then b.value->>'value' end) as full_name,
     max(case when b.value->>'type' = 'age' 
         then b.value->>'value' end) as age,
     max(case when b.value->>'type' = 'last_album' 
         then b.value->>'value' end) as last_album
from artists2 a, 
     json_array_elements(a.facts) b
group by a.artist
order by a.artist;

我在这里编辑了SqlFiddle链接。

答案 1 :(得分:0)

我会选择crosstab()功能。 @Eriwn真的good answers使用这种方法。

示例:

SELECT * FROM crosstab(
    'WITH data AS (
      SELECT artist,fact
      FROM artists a, jsonb_array_elements(a.facts) fact
    )
    SELECT artist,type,value
    FROM data,jsonb_to_record(data.fact) AS x(type text,value text)',
    'WITH data AS (
      SELECT artist,fact
      FROM artists a, jsonb_array_elements(a.facts) fact
     )
    SELECT DISTINCT type
   FROM data,jsonb_to_record(data.fact) AS x(type text,value text)'
) AS ct (artist text,age text,full_name text,last_album TEXT);

结果:

 artist | age  |  full_name   | last_album 
--------+------+--------------+------------
 adele  |      | Adele Laurie | 25
 taylor | 1989 |              | 25
(2 rows)