2015-11-24 105 views
0

變換SQL 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"}]'); 

有事實上的固定數量的「類型」 S,但不是每個藝術家都會有各自的事實。我怎樣才能選擇每個事實類型列的結果,缺少事實名稱的空值呢?

所需的輸出:

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

在表格的軌道是從哪裏來的? –

+0

哎呀,不好複製粘貼,現在定 –

+1

第一行有一個定義的對象'{「類型」:「FULL_NAME」,「值」:「阿黛爾勞瑞」}',而第二個沒有'{「時代」:「 25「}'是第二個模式正確或者是缺少一個類型,如'{」type「:」age「,」value「:」25「}' –

回答

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

唯一的區別是,你並不真的需要別人的case語句。

這是沒有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連接起來,在這裏查詢。

+0

這很好用!我在查看sqlfiddle時遇到了問題。你能修復鏈接並編輯回答問題嗎? –

+0

我用查詢編輯了它。 sqlfiddle鏈接正在我這裏工作。它有時停止工作,最近它不穩定。再試一次。 –

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) 
+0

您正在使用四個select語句來完成只需要一個的操作。在大型數據集中,這將是一個矯枉過正的問題。始終使用K.I.S.S.方法:) –

+0

是的,使用交叉表,你不能重用實際的文本SQL查詢,除非你顯示一個。使用2選擇的缺點,但添加更多屬性到Json中SQL不應該有很大的改變@JorgeCampos –