PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Abfragekombinationen mit verschachteltem Array von Datensätzen im JSON-Datentyp

Angesichts dieser Tabelle (die Sie in einer Form wie dieser bereitgestellt haben sollten):

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-Einträge bekannter, übersetzbarer Typen

Verwenden Sie json_populate_recordset() zum Entschachteln des Recordsets "objects" .Die Funktion erfordert einen registrierten Zeilentyp, um die Namen und Datentypen der resultierenden Spalten zu definieren. Für den Zweck dieser Demo oder allgemein für Ad-hoc-Abfragen, eine temp table modelliert nach "objects" bietet dasselbe:

CREATE TEMP TABLE obj(album int, src text, pos text);

So finden Sie 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;

Jedes Objekt zählt, egal ob aus der gleichen Reihe oder nicht. Sie haben nicht definiert, wie genau damit umgegangen werden soll. Folglich rep_id kann mehrfach im Array ids auftauchen . Fügen Sie DISTINCT hinzu zu array_agg() mögliche Duplikate zu falten. Die Anzahl ct kann größer sein als die Länge des Arrays ids in diesem Fall.

Erfordert Postgres 9.3 für die JSON-Funktionen und -Operatoren und den impliziten JOIN LATERAL .

JSON-Einträge von unbekanntem oder nicht übersetzbarem Typ

json_array_elements() entschachtelt einfach das json-Array, ohne das Ergebnis in eine SQL-Zeile umzuwandeln. Greifen Sie entsprechend mit JSON-Operatoren auf einzelne Felder zu.

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;