2017-02-22 23 views
1

JSONBカラムにネストされたデータを平坦化する方法を見ています。私はのような応答が返されますクエリを探していますPostgresのネストされたJSONBカラムを平滑化する

id | JSONB 
--------------------- 
1 | {"brother": {"first_name":"Sam", "last_name":"Smith"}, "sister": {"first_name":"Sally", "last_name":"Smith"} 
2 | {"sister": {"first_name":"Jill"}} 

:例として は、のような行を持つ

(JSONB)私たちは、テーブルのuser_id(int型)を持つユーザーと兄弟を持っていると言います。

id | sibling | first_name | last_name 
------------------------------------- 
1 | "brother" | "Sam"  | "Smith" 
1 | "sister" | "Sally" | "Smith" 
2 | "sister" | "Jill"  | null 
+0

postgresバージョン? –

+0

@ VaoTsunバージョン9.4.9 –

+0

json keys first_nameとlast_nameは一定ですか? –

答えて

1

これを開発するには、psqlで使用してください。結果は

WITH fields AS (
    SELECT DISTINCT jff.key 
     FROM t1, 
      jsonb_each(jsonb) AS jf, 
      jsonb_each(jf.value) AS jff 
) 
SELECT * FROM fields; 

key  
------------ 
first_name 
last_name 
x_name 

次の段階である第1のタスクが可能なキーの見つかったリストにある

CREATE VIEW t1 AS (
     SELECT 1 AS id, '{"brother": {"first_name":"Sam", "last_name":"Smith"}, "sister": {"first_name":"Sally", "last_name":"Smith"}}'::jsonb AS jsonb 
UNION SELECT 2, '{"sister": {"first_name":"Jill", "last_name":"Johnson"}}' 
UNION SELECT 3, '{"sister": {"first_name":"Jill", "x_name":"Johnson"}}' 
); 

:私は小さなビューt1を作成するコードを確認するには クエリを生成する:

SELECT 'SELECT id, jf.key as sibling, ' || (
    WITH fields AS (
     SELECT DISTINCT jff.key 
      FROM t1, 
       jsonb_each(jsonb) AS jf, 
       jsonb_each(jf.value) AS jff 
    ) 
    SELECT string_agg('jf.value->>''' || key || ''' as "' || key || '"', ',' ORDER BY key) 
     FROM fields 
) 
|| ' FROM t1, jsonb_each(jsonb) AS jf ORDER BY 1, 2, 3;' AS cmd; 

それは返します:あなたは、クエリを呼び出すことができその後

\gset 

                    cmd                     
------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 
SELECT id, jf.key as sibling,jf.value->>'first_name' as "first_name",jf.value->>'last_name' as "last_name",jf.value->>'x_name' as "x_name" FROM t1, jsonb_each(jsonb) AS jf ORDER BY 1, 2, 3; 
(1 row) 

私はgsetを使用psqlの変数として結果を設定するには

:cmd 

id | sibling | first_name | last_name | x_name 
----+---------+------------+-----------+--------- 
    1 | brother | Sam  | Smith  | 
    1 | sister | Sally  | Smith  | 
    2 | sister | Jill  | Johnson | 
    3 | sister | Jill  |   | Johnson 
(4 rows) 

は、外部の言語からそれを実行するには戻りSQLコマンドよりpostgres関数を作成することができます:

CREATE OR REPLACE FUNCTION build_query(IN tname text, OUT cmd text) AS $sql$ 
BEGIN 
    EXECUTE $cmd$ 
      SELECT 'SELECT id, jf.key as sibling, ' || (
        WITH fields AS (
         SELECT DISTINCT jff.key 
          FROM t1, 
           jsonb_each(jsonb) AS jf, 
           jsonb_each(jf.value) AS jff 
        ) 
        SELECT string_agg('jf.value->>''' || key || ''' as "' || key || '"', ',' ORDER BY key) 
         FROM fields 
       ) 
     || ' FROM $cmd$ || quote_ident(tname) || $cmd$ , jsonb_each(jsonb) AS jf ORDER BY 1, 2, 3;'$cmd$ INTO cmd; 
    RETURN; 
END; 
$sql$ LANGUAGE plpgsql; 

SELECT * FROM build_query('t1'); 
                           cmd                        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
SELECT id, jf.key as sibling, jf.value->>'first_name' as "first_name",jf.value->>'last_name' as "last_name",jf.value->>'x_name' as "x_name" FROM t1 , jsonb_each(jsonb) AS jf ORDER BY 1, 2, 3; 
(1 row) 
関連する問題