É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;