PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Combinazioni di query con array di record nidificati nel tipo di dati JSON

Data questa tabella (che avresti dovuto fornire in una forma come questa):

CREATE TABLE reports (rep_id int primary key, data json);
INSERT INTO reports (rep_id, data)
VALUES 
  (1, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"},   {"album": 2, "src":"barB.png", "pos": "top"}],   "background":"background.png"}')
, (2, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"},   {"album": 2, "src":"barC.png", "pos": "top"}],   "background":"bacakground.png"}')
, (3, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "middle"},{"album": 2, "src":"barB.png", "pos": "middle"}],"background":"background.png"}')
, (4, '{"objects":[{"album": 1, "src":"fooA.png", "pos": "top"},   {"album": 3, "src":"barB.png", "pos": "top"}],   "background":"backgroundA.png"}')
;

Record JSON di tipo noto e traducibile

Usa json_populate_recordset() per annullare l'annidamento del recordset "objects" .La funzione richiede un tipo di riga registrato per definire i nomi e i tipi di dati delle colonne risultanti. Ai fini di questa demo o in generale per query ad hoc, una tabella temporanea modellato su "objects" fornisce lo stesso:

CREATE TEMP TABLE obj(album int, src text, pos text);

Per trovare the top 3 most common combinations ... of entries that have the same album, src, and background :

SELECT array_agg(r.rep_id) AS ids, count(*) AS ct
FROM   reports r
     , json_populate_recordset(null::obj, r.data->'objects') o
GROUP  BY r.data->>'background'
        , o.album
        , o.scr
ORDER  BY count(*) DESC
LIMIT  3;

Ogni oggetto conta, non importa se dalla stessa riga o meno. Non hai definito come gestirlo esattamente. Di conseguenza, rep_id può apparire più volte nell'array ids . Aggiungi DISTINCT a array_agg() piegare eventuali duplicati. Il conteggio ct può essere maggiore della lunghezza dell'array ids in questo caso.

Richiede Postgres 9.3 per le funzioni e gli operatori JSON e l'implicito JOIN LATERAL .

Record JSON di tipo sconosciuto o intraducibile

json_array_elements() disnida semplicemente l'array json senza trasformare il risultato in una riga SQL. Accedi ai singoli campi con gli operatori JSON di conseguenza.

SELECT array_agg(r.rep_id) AS ids, count(*) AS ct
FROM   reports r
     , json_array_elements(r.data->'objects') o
GROUP  BY r.data->>'background'
        , o->>'album'
        , o->>'scr'
ORDER  BY count(*) DESC
LIMIT  3;