【问题标题】:Get nested objects values from JSON in Postgres从 Postgres 中的 JSON 获取嵌套对象值
【发布时间】:2021-11-03 06:44:38
【问题描述】:

这是我的 Postgres DB 中的 JSON 列:

{
  "objekt_art": {
    "86": {
      "code": "86",
      "bezeichnung_de": "Kino",
      "bezeichnung_fr": "Cinéma",       
      "bezeichnung_it": "Cinema",
      "bezeichnung_en": null,
      "kurz_bezeichnung_de": "Kino",
      "relevant_fuer_berechnung_steuerquote": true
    },
    "27": {
      "code": "27",
      "bezeichnung_de": "Kiosk",
      "bezeichnung_fr": "Kiosque",
      "bezeichnung_it": "Chiosco",
      "bezeichnung_en": null,
      "kurz_bezeichnung_de": "Kiosk",
      "relevant_fuer_berechnung_steuerquote": true
    }
  }
}

我需要能够查询 bezechnung_de,例如 code = 86。 我可以从另一个表传递的代码数量。

例如,我如何使用两列进行查询。一个是数字,第二个是 bezeichnung_de。

像这样:

Code Bez
86   Kino

【问题讨论】:

  • 您使用的是哪个 Postgres 版本?
  • 使用正确规范化的数据模型会容易得多
  • 在jsonb 或json 或text 列中使用哪种数据类型?
  • Postgres 10.8,它是一个文本字段,所以我必须将它转换为 json 或 jsonb

标签: json postgresql object


【解决方案1】:

连接数据的示例数据结构和示例表:dbfiddle

select
  je.value -> 'code' as "Code",
  je.value -> 'bezeichnung_de' as "Bez"
from
  test t
  cross join jsonb_each((data::jsonb ->> 'objekt_art')::jsonb) je
  -- In table test_join I insert value 86 for join record
  inner join test_join tj on je.key::int = tj.json_id

【讨论】:

  • (data::jsonb ->> 'objekt_art')::jsonb可以简化为data::jsonb -> 'objekt_art'
【解决方案2】:

如您所知,这相当简单:

select t.the_column -> 'objekt_art' -> '86' ->> 'code' as code,
       t.the_column -> 'objekt_art' -> '86' ->> 'bezeichnung_de' as bez
from the_table t
where ...

值'86' 可以是一个参数。不过,实际上并不需要选择代码的第一个表达式,因为您可以直接将其替换为常量值(=parameter)。

如果“外部”JSON 键的值与 code 值不同,您可以使用如下内容:

select o.value ->> 'code' as code, 
       o.value ->> 'bezeichnung_de' as bez
from the_table t
  cross join jsonb_each(t.the_column -> 'objekt_art') o(key, value)
where o.key = '86'
  and ... other conditions ...

如果你使用的是 Postgres 13 或更高版本,这也可以写成 JSON 路径表达式:

select a.item ->> 'code' as code,
       a.item ->> 'bezeichnung_de' as bez
from (
  select jsonb_path_query_first(t.the_column, '$.objekt_art.* ? (@.code == "86")') as item
  from the_table t
  where ....
) a

所有示例都假定该列是使用应有的数据jsonb 定义的。如果不是,您需要投射它:the_column::jsonb

【讨论】:

  • 是的,但问题是我以前不知道 86。我有另一个表,其中有一列(objekt_art),里面有数字。我必须能够对该值和代码值进行某种连接。
  • @user2210516:您必须在某些时候比较值86。请参阅我的编辑以获取替代方案。我发现 JSON 结构非常值得怀疑,因为它在两个不同的位置重复相同的“代码值”。访问您不知道其值的键有点挑战性。使用适当的规范化数据模型,这一切都会变得容易得多。
  • 是的,如果不是数字的双重位置,我想我可以单独解决问题。感谢您的帮助
  • 如果您可以确定重复的值永远不会不同步,那么第一个查询就可以正常工作。
猜你喜欢
  • 1970-01-01
  • 2020-05-10
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 2019-07-08
相关资源
最近更新 更多