sql >> Databasteknik >  >> RDS >> PostgreSQL

Frågekombinationer med kapslad array av poster i JSON-datatypen

Med tanke på den här tabellen (som du borde ha tillhandahållit i ett formulär som detta):

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-poster av välkänd, översättbar typ

Använd json_populate_recordset() för att ta bort postuppsättningen "objects" . Funktionen kräver en registrerad radtyp för att definiera namn och datatyper för resulterande kolumner. För syftet med denna demo eller generellt för ad-hoc-frågor, en temptabell modellerad efter "objects" ger samma:

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

För att hitta 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;

Varje objekt räknas, oavsett om det kommer från samma rad eller inte. Du definierade inte exakt hur du skulle hantera det. Följaktligen, rep_id kan dyka upp flera gånger i arrayen ids . Lägg till DISTINCT till array_agg() för att vika eventuella dubbletter. Antalet ct kan vara längre än längden på arrayen ids i det här fallet.

Kräver Postgres 9.3 för JSON-funktionerna och -operatorerna och den implicita JOIN LATERAL .

JSON-poster av okänd eller oöversättbar typ

json_array_elements() tar bara bort json-arrayen utan att omvandla resultatet till en SQL-rad. Få åtkomst till individuella fält med JSON-operatörer i enlighet med detta.

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;



  1. Betygsätt din databas Performance Monitoring Setup

  2. Hur aktiverar jag mysqlnd för php?

  3. Hur tvingar jag Postgres att använda ett visst index?

  4. SQLite välj rader om tidsstämpeln matchar dagens datum