Gezien deze tabel (die u in een vorm als deze had moeten verstrekken):
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"}')
;
JSON-records van het bekende, vertaalbare type
Gebruik json_populate_recordset()
voor het verwijderen van de recordset "objects"
.De functie vereist een geregistreerd rijtype om de namen en gegevenstypen van resulterende kolommen te definiëren. Voor deze demo of in het algemeen voor ad-hocvragen, een tijdelijke tabel gemodelleerd naar "objects"
biedt hetzelfde:
CREATE TEMP TABLE obj(album int, src text, pos text);
Om the top 3 most common combinations
te vinden ... 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;
Elk object telt, of het nu uit dezelfde rij komt of niet. Je hebt niet gedefinieerd hoe je dat precies moet aanpakken. Bijgevolg, rep_id
kan meerdere keren verschijnen in de array ids
. Voeg DISTINCT
toe naar array_agg()
mogelijke duplicaten te vouwen. De telling ct
kan groter zijn dan de lengte van de array ids
in dit geval.
Vereist Postgres 9.3 voor de JSON-functies en -operators en de impliciete JOIN LATERAL
.
JSON-records van onbekend of onvertaalbaar type
json_array_elements()
unnest gewoon de json-array zonder het resultaat in een SQL-rij te transformeren. Toegang tot individuele velden met JSON-operators dienovereenkomstig.
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;