通过以下查询,我几乎在结构上达到了我想要的:
SELECT
t.id,
t.name,
json_agg(places) AS places
FROM
trips t
-- trips_cities
INNER JOIN (
SELECT
tc.city_id,
tc.trip_id,
json_agg(json_build_object(
'city_id', tc.city_id,
'airports', airports
)) AS places
FROM
trips_cities tc
-- airports
LEFT JOIN (
SELECT
a.id,
a.country_id,
json_agg(json_build_object(
'airport_id', a.id
)) AS airports
FROM airports a
GROUP BY a.id
) a ON a.id = ANY(tc.airport_ids)
-- /airports
GROUP BY 1, 2
) tc ON tc.trip_id = t.id
-- /trips_cities
GROUP BY 1
但是,它不是将机场作为数组,而是返回重复的城市:
[
[
{
"city_id": 20,
"airports": [
{
"airport_id": 2
}
]
},
{
"city_id": 20,
"airports": [
{
"airport_id": 1
}
]
}
]
]
不是我希望的那样,我似乎无法弄清楚以下分组:
[
[
{
"city_id": 20,
"airports": [
{
"airport_id": 2
},
{
"airport_id": 1
}
]
}
]
]
一些数据:
INSERT INTO trips (id, name)
VALUES (1, 'My First Trip'),
(2, 'My Second Trip');
INSERT INTO trips_cities (trip_id, city_id, airport_ids)
VALUES (1, 'London', {1,2}),
(2, 'Paris', {1}),
(3, 'Berlin', {2});
INSERT INTO airports(id, name)
VALUES (1, 'Heathrow'),
(2, 'Gatwick');
表结构如下:
行程
id
trips_cities
trip_id
city_id
airport_ids[]
机场
id
总结:
trips_cities
trips_cities
,请加入所有airports
答案 0 :(得分:1)
首先:您的样本数据不适合您的INSERT
语句。例如,您的city_id
是text
而不是integer
值。在我的示例中,我使用了INSERT
语句。
第二:如果不是真的,请不要存储数组。请规范化您的数据。存储数组有很多缺点:搜索值,索引值,联接值等确实很麻烦。在大多数情况下,您需要从一开始就取消嵌套这些值。
我不太确定两个嵌套的外部数组应该是什么,但是可以这样创建city / airports对象:
SELECT
trip_id,
json_build_object( -- 4
'city_id', city_id,
'airports', json_agg(json_build_object('airport_id', airport_id)) -- 2,3
)
FROM trips_cities,
unnest(airport_ids) as airport_id -- 1
GROUP BY trip_id, city_id -- 3
如果您需要其他表中的一些数据,例如机场名称,当然,您可以加入他们:
SELECT
trip_id,
json_build_object(
'city_id', city_id,
'airports', json_agg(
json_build_object(
'airport_id', airport_id,
'name', a.name
)
)
)
FROM trips_cities,
unnest(airport_ids) as airport_id
JOIN airports a ON a.id = airport_id
GROUP BY trip_id, city_id