2017-02-22 1 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"}} 

: 예를 들어 , 우리는 같은 행 USER_ID (INT) 및 형제 자매 (JSONB)

와 테이블 사용자가 있다고 가정 :

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 키 first_name 및 last_name은 일정합니까? .. –

답변

1

나는 이것을 psql에서 사용하기 위해 개발했다. 내가 작은보기 t1를 만드는 코드를 확인하려면

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"}}' 
); 

첫 번째 작업 가능한 키의 발견 목록입니다 :

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 

다음 단계는 검색어 생성 :

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 명령보다 포스트 그레스 함수를 만들 수 있습니다 :

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) 
관련 문제