このテーブル(このような形式で提供する必要があります)を考えると:
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レコード
json_populate_recordset()
を使用します レコードセットのネストを解除するための"objects"
この関数では、結果の列の名前とデータ型を定義するために、登録された行タイプが必要です。このデモの目的で、または一般的にアドホッククエリの場合、一時テーブル "objects"
をモデルにしています 同じを提供します:
CREATE TEMP TABLE obj(album int, src text, pos text);
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;
同じ行からであるかどうかに関係なく、各オブジェクトがカウントされます。あなたはそれを正確に処理する方法を定義していませんでした。したがって、rep_id
配列ids
に複数回ポップアップする可能性があります 。 DISTINCT
を追加します array_agg()
へ 可能な重複を折ります。カウントct
配列のids
の長さより大きくすることができます この場合。
JSON関数と演算子および暗黙のJOIN LATERAL
にはPostgres9.3が必要です 。
不明または翻訳不可能なタイプのJSONレコード
json_array_elements()
結果をSQL行に変換せずに、json配列のネストを解除するだけです。それに応じて、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;