Query combinations with nested array of records in JSON datatype

前端 未结 1 1450
没有蜡笔的小新
没有蜡笔的小新 2020-12-06 07:42

I\'m working on a Rails application that utilizes the Postgres JSON data type. I have a JSON column called data in a table called reports

1条回答
  •  感情败类
    2020-12-06 08:27

    Given this table (which you should have provided in a form like this):

    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 records of well known, translatable type

    Use json_populate_recordset() for unnesting the recordset "objects". The function requires a registered row type to define the names and data types of resulting columns. For the purpose of this demo or generally for ad-hoc queries, a temp table modeled after "objects" provides the same:

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

    To find 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;
    

    Each object counts, no matter whether from the same row or not. You did not define how to handle that exactly. Consequently, rep_id can pop up multiple times in the array ids. Add DISTINCT to array_agg() to fold possible duplicates. The count ct can be greater then the length of the array ids in this case.

    Requires Postgres 9.3 for the JSON functions and operators and the implicit JOIN LATERAL.

    JSON records of unknown or untranslatable type

    json_array_elements() just unnests the json array without transforming the result into a SQL row. Access individual fields with JSON operators accordingly.

    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;

    0 讨论(0)
提交回复
热议问题