PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Combinaisons de requêtes avec tableau imbriqué d'enregistrements dans le type de données JSON

Étant donné ce tableau (que vous auriez dû fournir sous une forme comme celle-ci) :

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

Enregistrements JSON de type bien connu et traduisible

Utilisez json_populate_recordset() pour désimbriquer le jeu d'enregistrements "objects" .La fonction nécessite un type de ligne enregistré pour définir les noms et les types de données des colonnes résultantes. Pour les besoins de cette démo ou plus généralement pour les requêtes ad hoc, une table temporaire modélisé d'après "objects" fournit la même :

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

Pour trouver 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;

Chaque objet compte, qu'il soit de la même rangée ou non. Vous n'avez pas défini comment gérer cela exactement. Par conséquent, rep_id peut apparaître plusieurs fois dans le tableau ids . Ajouter DISTINCT à array_agg() pour plier d'éventuels doublons. Le compte ct peut être supérieur à la longueur du tableau ids dans ce cas.

Nécessite Postgres 9.3 pour les fonctions et opérateurs JSON et le JOIN LATERAL implicite .

Enregistrements JSON de type inconnu ou intraduisible

json_array_elements() désimbrique simplement le tableau json sans transformer le résultat en une ligne SQL. Accédez aux champs individuels avec les opérateurs JSON en conséquence.

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;