Med tanke på den här tabellen (som du borde ha tillhandahållit i ett formulär som detta):
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-poster av välkänd, översättbar typ
Använd json_populate_recordset()
för att ta bort postuppsättningen "objects"
. Funktionen kräver en registrerad radtyp för att definiera namn och datatyper för resulterande kolumner. För syftet med denna demo eller generellt för ad-hoc-frågor, en temptabell modellerad efter "objects"
ger samma:
CREATE TEMP TABLE obj(album int, src text, pos text);
För att hitta 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;
Varje objekt räknas, oavsett om det kommer från samma rad eller inte. Du definierade inte exakt hur du skulle hantera det. Följaktligen, rep_id
kan dyka upp flera gånger i arrayen ids
. Lägg till DISTINCT
till array_agg()
för att vika eventuella dubbletter. Antalet ct
kan vara längre än längden på arrayen ids
i det här fallet.
Kräver Postgres 9.3 för JSON-funktionerna och -operatorerna och den implicita JOIN LATERAL
.
JSON-poster av okänd eller oöversättbar typ
json_array_elements()
tar bara bort json-arrayen utan att omvandla resultatet till en SQL-rad. Få åtkomst till individuella fält med JSON-operatörer i enlighet med detta.
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;