sql >> Base de Datos >  >> RDS >> PostgreSQL

Combinaciones de consulta con matriz anidada de registros en tipo de datos JSON

Dada esta tabla (que debería haber proporcionado en un formulario 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 conocido y traducible

Usa json_populate_recordset() para anidar el conjunto de registros "objects" .La función requiere un tipo de fila registrado para definir los nombres y tipos de datos de las columnas resultantes. A los efectos de esta demostración o, en general, para consultas ad-hoc, una tabla temporal modelado a partir de "objects" proporciona lo mismo:

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 cuenta, sin importar si es de la misma fila o no. No definiste cómo manejar eso exactamente. En consecuencia, rep_id puede aparecer varias veces en la matriz ids . Agregar DISTINCT a array_agg() para plegar posibles duplicados. El conteo ct puede ser mayor que la longitud de la matriz ids en este caso.

Requiere Postgres 9.3 para las funciones y operadores JSON y el implícito JOIN LATERAL .

Registros JSON de tipo desconocido o intraducible

json_array_elements() simplemente anula la matriz json sin transformar el resultado en una fila SQL. Acceda a campos individuales con operadores JSON según corresponda.

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;