Като се има предвид тази таблица (която трябваше да предоставите във форма като тази):
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 записи от добре познат, преводим тип
Използвайте json_populate_recordset()
за премахване на набора от записи "objects"
.Функцията изисква регистриран тип ред, за да дефинира имената и типовете данни на получените колони. За целите на тази демонстрация или като цяло за ad-hoc заявки, временна таблица моделиран след "objects"
предоставя същото:
CREATE TEMP TABLE obj(album int, src text, pos text);
За да намерите 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;
Всеки обект се брои, независимо дали от един и същи ред или не. Не сте дефинирали как точно да се справите с това. Следователно, rep_id
може да изскача няколко пъти в масива ids
. Добавете DISTINCT
към array_agg()
за сгъване на възможни дубликати. Броят ct
може да бъде по-голямо от дължината на масива ids
в този случай.
Изисква Postgres 9.3 за функциите и операторите JSON и имплицитното JOIN LATERAL
.
JSON записи от неизвестен или непреводим тип
json_array_elements()
просто премахва json масива, без да трансформира резултата в SQL ред. Достъп до отделни полета с JSON оператори съответно.
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;