Dada esta tabela (que você deveria ter fornecido em um formulário como este):
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"}')
;
Registros JSON de tipo bem conhecido e traduzível
Use
json_populate_recordset()
para desaninhar o conjunto de registros "objects"
.A função requer um tipo de linha registrado para definir os nomes e tipos de dados das colunas resultantes. Para fins desta demonstração ou geralmente para consultas ad hoc, uma tabela temporária modelado após "objects"
fornece o mesmo:CREATE TEMP TABLE obj(album int, src text, pos text);
Para encontrar
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;
Cada objeto conta, independentemente de ser da mesma linha ou não. Você não definiu como lidar com isso exatamente. Consequentemente,
rep_id
pode aparecer várias vezes no array ids
. Adicionar DISTINCT
para array_agg()
para dobrar possíveis duplicatas. A contagem ct
pode ser maior que o comprimento do array ids
nesse caso. Requer Postgres 9.3 para as funções e operadores JSON e o
JOIN LATERAL
implícito . Registros JSON de tipo desconhecido ou intraduzível
json_array_elements()
apenas desaninha a matriz json sem transformar o resultado em uma linha SQL. Acesse campos individuais com operadores JSON de acordo. 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;