PostgreSQL:根据特定列将多行汇总为JSON数组

时间:2018-10-31 15:22:14

标签: sql json postgresql postgresql-9.3

我有一个表格 data_tracks ,其中包含在特定时间( created_at )记录的点(纬度经度) >),并属于行程( trip_log_id )。行程通常至少有两个点(起点和终点)。

表: data_tracks

  • created_at : text
  • latitude : float
  • longitude : float
  • trip_log_id : integer

我想生成一个由数组数组组成的JSON输出,而每个内部数组都包含行程的聚合点(如trip_log_id所示)。

由两次旅行组成的示例:

[

  [
    {
      "latitude": 52.504873,
      "longitude": 13.396681,
      "recorded_at": "2018-10-11T15:16:32.775"
    },
    {
      "latitude": 52.505225,
      "longitude": 13.396976,
      "recorded_at": "2018-10-11T15:16:32.807"
    },
    {
      "latitude": 52.505372,
      "longitude": 13.397035,
      "recorded_at": "2018-10-11T15:16:32.835"
    },
  ],

  [
    {
      "latitude": 52.5242370846803,
      "longitude": 13.3443558528637,
      "recorded_at": "2018-10-11T11:22:54.666"
    },
    {
      "latitude": 52.5242366166393,
      "longitude": 13.3443558656828,
      "recorded_at": "2018-10-11T11:22:54.727"
    }
  ]

]

根据另一则帖子[1]的建议,我能够生成非常接近所需内容的输出。但是,输出被解释为文本,从而引入了不需要的转义字符。此外,外部数组丢失。

该查询应在PostgreSQL 9.3上运行。

自适应查询:

SELECT Array_agg(rw) 
FROM  (SELECT trip_log_id, 
              (SELECT To_json(Array_agg(Row_to_json(t))) 
               FROM   (SELECT latitude, 
                              longitude, 
                              created_at AS recorded_at 
                       FROM   public.data_tracks 
                       WHERE  trip_log_id = b.trip_log_id) t) rw 
       FROM   data_tracks b 
       GROUP  BY trip_log_id) z; 

输出:

{

    "[
        {
            \"latitude\":52.504873,
            \"longitude\":13.396681,
            \"recorded_at\":\"2018-10-11T15:16:32.775\"
        },
        {
            \"latitude\":52.505225,
            \"longitude\":13.396976,
            \"recorded_at\":\"2018-10-11T15:16:32.807\"
        },
        {
            \"latitude\":52.505372,
            \"longitude\":13.397035,
            \"recorded_at\":\"2018-10-11T15:16:32.835\"
        },
        {
            \"latitude\":52.505686,
            \"longitude\":13.397218,
            \"recorded_at\":\"2018-10-11T15:16:32.871\"
        },
        {
            \"latitude\":52.505921,
            \"longitude\":13.397389,
            \"recorded_at\":\"2018-10-11T15:16:32.906\"
        },
        {
            \"latitude\":52.506166,
            \"longitude\":13.397593,
            \"recorded_at\":\"2018-10-11T15:16:32.936\"
        },
        {
            \"latitude\":52.50647,
            \"longitude\":13.397856,
            \"recorded_at\":\"2018-10-11T15:16:32.969\"
        },
        {
            \"latitude\":52.506786,
            \"longitude\":13.398065,
            \"recorded_at\":\"2018-10-11T15:16:33\"
        }
    ]",

    "[
        {
            \"latitude\":52.5242370846803,
            \"longitude\":13.3443558528637,
            \"recorded_at\":\"2018-10-11T11:22:54.666\"
        },
        {
            \"latitude\":52.5242366166393,
            \"longitude\":13.3443558656828,
            \"recorded_at\":\"2018-10-11T11:22:54.727\"
        }
    ]"

}

1 个答案:

答案 0 :(得分:1)

免责声明:仅适用于Postgres 9.4 + 9.4及更高版本,为Postgres添加了对JSON的强大支持。 9.3已经不受支持。您应该真正升级数据库。

demo:db<>fiddle

SELECT json_agg(trips)
FROM (
    SELECT 
        json_agg(
            json_build_object(
                'recorded_at', created_at, 
                'latitude', latitude, 
                'longitude', longitude
            )
        ) as trips
    FROM data_tracks
    GROUP by trip_log_id
)s
  1. json_build_object创建您的主要json对象
  2. json_agg() ... GROUP BY trip_log_id将这些json对象分组为一个行程对象
  3. 第二json_agg将所有行程汇总到一个阵列中

demo:SQL Fiddle

版本9.3 (严格建议不要!)

SELECT json_agg(trips)
FROM (
    SELECT 
        json_agg(
            ('{"recorded_at":"' || created_at || 
            '","latitude":' || latitude || 
            ',"longitude":' || longitude || '}')::json
        ) as trips
    FROM data_tracks
    GROUP by trip_log_id
)s