Biorąc pod uwagę tę tabelę (którą powinieneś podać w takiej formie):
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"}')
;
Rekordy JSON znanego, możliwego do przetłumaczenia typu
Użyj json_populate_recordset()
do rozgnieżdżania zestawu rekordów "objects"
.Funkcja wymaga zarejestrowanego typu wiersza w celu zdefiniowania nazw i typów danych wynikowych kolumn. Na potrzeby tego pokazu lub ogólnie dla zapytań ad hoc tabela tymczasowa wzorowane na "objects"
zapewnia to samo:
CREATE TEMP TABLE obj(album int, src text, pos text);
Aby znaleźć 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;
Liczy się każdy przedmiot, bez względu na to, czy z tego samego rzędu, czy nie. Nie określiłeś dokładnie, jak sobie z tym poradzić. W związku z tym rep_id
może pojawiać się wiele razy w tablicy ids
. Dodaj DISTINCT
do array_agg()
złożyć ewentualne duplikaty. Liczba ct
może być większa niż długość tablicy ids
w tym przypadku.
Wymaga Postgres 9.3 dla funkcji i operatorów JSON oraz niejawnego JOIN LATERAL
.
Rekordy JSON nieznanego lub nieprzetłumaczalnego typu
json_array_elements()
po prostu rozpakowuje tablicę json bez przekształcania wyniku w wiersz SQL. Uzyskaj odpowiedni dostęp do poszczególnych pól za pomocą operatorów JSON.
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;