PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Spłaszczanie kolumny Postgres zagnieżdżonej JSONB

Rozwijam się do tego używać go w psql .Aby sprawdzić kod, tworzę mały widok 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"}}'
);

Pierwszym zadaniem jest znalezienie listy możliwych kluczy:

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

Wynik:

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

Następnym krokiem jest wygenerowanie zapytań:

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;

Zwraca:

                                                                                  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)

Aby ustawić wynik jako zmienną psql, używam gset :

\gset

Następnie możesz wywołać zapytanie:

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

Aby uruchomić go z języków zewnętrznych, możesz utworzyć funkcję postgres niż zwrócić polecenie 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)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Używanie razem sqldf i RPostgreSQL

  2. Prosta instrukcja Postgresql - nazwa kolumny nie istnieje

  3. PostgreSQL Reverse LIKE

  4. SQLAlchemy i Postgres UnicodeDecodeError

  5. Jak usunąć bazę danych szablonów z PostgreSQL?