sql >> Database >  >> RDS >> PostgreSQL

een geneste jsonb recursief afvlakken in postgres zonder onbekende diepte en onbekende sleutelvelden

Voorbeeldopstelling:

create table my_table(id int, data jsonb);
insert into my_table values
(1,
$${
   "type": "a type",
   "form": "a form",
   "contact": {
       "name": "a name",
       "phone": "123-456-78",
       "type": "contact type",
       "parent": {
           "id": "444",
           "type": "parent type" 
           } 
    }
}$$);

De recursieve query voert jsonb_each() uit voor elk json-object dat op elk niveau wordt gevonden. Nieuwe sleutelnamen bevatten het volledige pad vanaf de root:

with recursive flat (id, key, value) as (
    select id, key, value
    from my_table,
    jsonb_each(data)
union
    select f.id, concat(f.key, '.', j.key), j.value
    from flat f,
    jsonb_each(f.value) j
    where jsonb_typeof(f.value) = 'object'
)
select id, jsonb_pretty(jsonb_object_agg(key, value)) as data
from flat
where jsonb_typeof(value) <> 'object'
group by id;

 id |                   data                   
----+------------------------------------------
  1 | {                                       +
    |     "form": "a form",                   +
    |     "type": "a type",                   +
    |     "contact.name": "a name",           +
    |     "contact.type": "contact type",     +
    |     "contact.phone": "123-456-78",      +
    |     "contact.parent.id": "444",         +
    |     "contact.parent.type": "parent type"+
    | }
(1 row)

Als u een plat overzicht van deze gegevens wilt krijgen, kunt u de functie create_jsonb_flat_view() gebruiken beschreven in dit antwoord Geaggregeerde sleutel/waarde-paren uit een JSONB-veld afvlakken?

U moet een tabel (of weergave) maken met afgevlakte jsonb:

create table my_table_flat as 
-- create view my_table_flat as 
with recursive flat (id, key, value) as (
-- etc as above
-- but without jsonb_pretty()

Nu kunt u de functie op de tafel gebruiken:

select create_jsonb_flat_view('my_table_flat', 'id', 'data');

select * from my_table_flat_view;


 id | contact.name | contact.parent.id | contact.parent.type | contact.phone | contact.type |  form  |  type  
----+--------------+-------------------+---------------------+---------------+--------------+--------+--------
  1 | a name       | 444               | parent type         | 123-456-78    | contact type | a form | a type
(1 row)

De oplossing werkt in Postgres 9.5+, omdat het de jsonb-functie gebruikt die in deze versie is geïntroduceerd. Als uw serverversie ouder is, wordt het ten zeerste aanbevolen om Postgres toch te upgraden om jsonb efficiënt te gebruiken.




  1. Alias ​​verwijderen in door Slick gegenereerde zoekopdrachten

  2. Ondersteunt Microsoft OLE DB Provider voor SQL Server TLS 1.2?

  3. Hiaten opvullen in data die zijn geretourneerd uit database - pure SQL-oplossing mogelijk?

  4. MySQL converteert datumreeks naar Unix-tijdstempel