代码之家  ›  专栏  ›  技术社区  ›  Tyler DeWitt

Postgres将jsonb单元展平到视图中的行中

  •  2
  • Tyler DeWitt  · 技术社区  · 5 年前

    我有一个简单的Postgres表:

        Column    │         Type         │ Modifiers
    ──────────────┼──────────────────────┼──────────────────────
     id           │ integer              │ not null default
     data         │ jsonb                │
    

    以下是一个简化的数据结构 data :

    {
      "id": 3,
      "date": "2019-01-01",
      "well_report_table":
        [
          {"element": "methane",
          "yield": 6,
          "price": 2.10
          },
          {"element": "pentane",
          "yield": 6,
          "price": 2.10
          },
          {"element": "butane",
          "yield": 6,
          "price": 3.50
          }
        ],
      "cost_report_table":
        [
          {"item": "fuel",
          "charge": 6.30
          },
          {"item": "lease",
          "charge": 200
          }
        ]
    }
    

    我想用下面的列在视图中展开这个:

    id | date | well_report_table_methane_yield | well_report_table_methane_price | well_report_table_pentane_yield | well_report_table_pentane_price | well_report_table_butane_yield | well_report_table_butane_price |cost_report_table_fuel_charge | cost_report_table_lease_charge
    

    我的数组中的对象有一个标识符,我想将它附加到数组对象名中,然后遍历对象中的其他键,并将列 .

    这个问题让我很接近: Postgres: Flatten aggregated key/value pairs from a JSONB field?

    我不完全确定这在plpgsql中是可能的,所以如果我只需要用Ruby/python之类的脚本语言生成视图文本,然后创建一个视图,我可以接受。

    理想情况下,我可以使用 jsonb_array_elements jsonb_each 为了避免中间表(我当前的所有尝试都需要中间视图),但我还没有找到这种神奇的组合。

    1 回复  |  直到 5 年前
        1
  •  1
  •   klin    5 年前

    这不是关于展平JSON数组的一般问题,因为数组中隐藏了一个特定的逻辑。您可以在此函数中实现逻辑:

    create or replace function flat_array(data jsonb, title text, item text)
    returns jsonb language sql immutable as $$
        select jsonb_object_agg(format('%s_%s_%s', title, elem->>item, key), value)
        from jsonb_array_elements(data->title) as arr(elem)
        cross join jsonb_each(elem)
        where key <> item
    $$;
    

    查询:

    select 
        jsonb_build_object('id', data->'id', 'date', data->'date') ||
        flat_array(data, 'well_report_table', 'element') ||
        flat_array(data, 'cost_report_table', 'item')
    from my_table
    

    给出对象:

    {
        "id": 3,
        "date": "2019-01-01",
        "cost_report_table_fuel_charge": 6.30,
        "cost_report_table_lease_charge": 200,
        "well_report_table_butane_price": 3.50,
        "well_report_table_butane_yield": 6,
        "well_report_table_methane_price": 2.10,
        "well_report_table_methane_yield": 6,
        "well_report_table_pentane_price": 2.10,
        "well_report_table_pentane_yield": 6
    }
    

    可以按照中描述的方式转换为表格视图。 Flatten aggregated key/value pairs from a JSONB field?