【问题标题】:PostgreSQL json extractionPostgreSQL json 提取
【发布时间】:2019-12-11 13:05:19
【问题描述】:

我有来自 MongoDB 的航班预订的 json 数据。此数据插入到 PostgreSQL 表中,数据类型为 json。行程信息具有以下结构。

[
  {
    "segments": {
      "1": {
        "airline": "G8",
        "flight_number": "761",
        "arrival-date": "2018-11-02T12:45:00",
        "arrival_airport": "CCU",
        "departure_date": "2018-11-02T11:35:00",
        "departure_airport": "BBI",
        "operating_airline": "G8",
        "stops": 0,
        "index": 1,
        "duration": 4200
      }
    }
  },
  {
    "segments": {
      "2": {
        "airline": "6E",
        "flight_number": "775",
        "arrival-date": "2018-11-03T00:30:00",
        "arrival_airport": "BBI",
        "departure_date": "2018-11-02T23:20:00",
        "departure_airport": "CCU",
        "operating_airline": "6E",
        "stops": 0,
        "index": 2,
        "duration": 4200
      }
    }
  }
]

段数未知。如何将其拆分为多个记录,以便每个段都成为记录? json_array_elements 是我已经在使用的函数,如果我使用json_array_elements(data->'flights')->'segments',我会得到这样的输出

{
  "1": {
    "airline": "AI",
    "flight_number": "20",
    "arrival_airport": "CCU",
    "arrival-date": "2018-10-17T16:40:00",
    "departure_date": "2018-10-17T14:25:00",
    "departure_airport": "DEL",
    "operating_airline": "AI",
    "stops": 0,
    "index": 1,
    "duration": 8100
  },
  "2": {
    "airline": "AI",
    "flight_number": "230",
    "arrival_airport": "DAC",
    "arrival-date": "2018-10-17T20:25:00",
    "departure_date": "2018-10-17T19:00:00",
    "departure_airport": "CCU",
    "operating_airline": "AI",
    "stops": 0,
    "index": 2,
    "duration": 3300
  }
}    

如何将其转换为单独的记录?我想执行这样的插入 -

insert into stage_itinerary (segment_id,airline,flight_number,arrival_aiport...)  select (....)

【问题讨论】:

    标签: sql json postgresql


    【解决方案1】:

    Click: demo:db<>fiddle

    你可以使用json_array_elements():

    SELECT
        elems
    FROM 
        mytable,
        json_array_elements(my_segments_column) elems
    

    如果要使用拆分数据更新表,则需要插入新数据并删除旧数据。这可以使用 CTE(WITH 子句)在一个查询中完成:

    Click: demo:db<>fiddle

    WITH del AS (
        DELETE FROM mytable
        RETURNING my_segments_column
    )
    INSERT INTO mytable
    SELECT
        elems
    FROM 
        del,
        json_array_elements(my_segments_column) elems;
    

    在 CTE 中,所有数据都被删除,但通过 RETURNING 子句返回。这个返回的数据用于计算如上所示的分割记录,之后插入。

    【讨论】:

    • 抱歉没有把问题说清楚。我已经编辑了我的问题。
    【解决方案2】:

    这实际上是一个非常好的堆叠多个横向查询的用例,因为每个横向查询都可以引用它之前定义的所有对象。

    SELECT a4.*
    FROM test
    , LATERAL (SELECT a1->'segments' a2 FROM jsonb_array_elements(a) a1) a1
    , LATERAL (SELECT value FROM jsonb_each(a2)) a3                    
    , LATERAL (SELECT * 
               FROM jsonb_to_record(a3) a4 
               ("index" int, stops int, airline text, duration int, 
                "arrival-date" timestamptz, flight_number text, departure_date text,
                arrival_airport text, departure_airport text, operating_airline text)
              ) a4                                 
    

    如果你有幸使用了 postgresql 12 或更高版本,那么上面的查询可以更优雅地写成:

    SELECT a2.*
    FROM test
    , LATERAL (SELECT * FROM jsonb_path_query(a, '$.*.*') a1 ) a1
    , LATERAL (SELECT * 
               FROM jsonb_to_record(a1) a2 
              ("index" int, stops int, airline text, duration int, 
               "arrival-date" timestamptz, flight_number text, departure_date text,
               arrival_airport text, departure_airport text, operating_airline text)
    ) a2
    

    这里是设置代码:

    CREATE TABLE test (a) AS SELECT 
    '[
      {
        "segments": {
          "1": {
            "airline": "G8",
            "flight_number": "761",
            "arrival-date": "2018-11-02T12:45:00",
            "arrival_airport": "CCU",
            "departure_date": "2018-11-02T11:35:00",
            "departure_airport": "BBI",
            "operating_airline": "G8",
            "stops": 0,
            "index": 1,
            "duration": 4200
          }
        }
      },
      {
        "segments": {
          "2": {
            "airline": "6E",
            "flight_number": "775",
            "arrival-date": "2018-11-03T00:30:00",
            "arrival_airport": "BBI",
            "departure_date": "2018-11-02T23:20:00",
            "departure_airport": "CCU",
            "operating_airline": "6E",
            "stops": 0,
            "index": 2,
            "duration": 4200
          }
        }
      }
    ]'::jsonb
    

    【讨论】:

      猜你喜欢
      • 2020-10-08
      • 1970-01-01
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      • 2012-03-02
      • 2012-11-04
      • 1970-01-01
      相关资源
      最近更新 更多