С помощью следующего запроса я почти достиг желаемого с точки зрения структуры:
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');
Табличные структуры следующие:
поездки
trips_cities
trip_id
city_id
airport_ids[]
аэропорты
В итоге:
- Для каждой поездки присоединяйтесь
trips_cities
- Для каждой
trips_cities
присоединяйтесь ко всем airports
- Создайте вложенную агг результаты, как в моем последнем JSON примере выше