PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Combinações de consulta com matriz aninhada de registros no tipo de dados JSON


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;