PostgreSQL 9.5:将 json_agg 个结果组合成单个 json 个对象
PostgreSQL 9.5: Combine json_agg results into single json object
我正在努力处理以下 SQL 查询:
有一个tabledata_tracks,坐标描述了一次旅行。每个行程都由 trip_log_id 唯一标识。到达旅行目的地后,用户需要参与调查。调查的答案存储在tablecrowd_sourcing_answers中。每个答案属于一个问题,位于tablecrowd_sourcing_questions.
我写了两个 SQL 查询 - 一个获取旅行的所有积分 JSON,另一个获取所有问答对:
获取旅行的所有问答对的查询:
SELECT json_agg(answer_single_trip)
FROM (SELECT json_agg(
json_build_object(
'tripId', trip_log_id,
'question', qt.question,
'answeringOption', qt."answeringOptions",
'answer', at.answer
)
) as crowdsourcing
FROM crowd_sourcing_questions as qt
INNER JOIN crowd_sourcing_answers as at ON at.crowd_sourcing_question_id = qt.id
GROUP BY trip_log_id) answer_single_trip;
及其输出:
[
{
"crowdsourcing": [
{
"tripId": 92,
"question": "Gab es auf der Strecke teilweise schlecht befahrbare Streckenabschnitte?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "2"
}
]
},
{
"crowdsourcing": [
{
"tripId": 91,
"question": "Gab es auf der Strecke teilweise schlecht befahrbare Streckenabschnitte?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "1"
}
]
},
{
"crowdsourcing": [
{
"tripId": 90,
"question": "Gab es auf der Strecke teilweise schlecht befahrbare Streckenabschnitte?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "0"
}
]
}
]
获取属于一个行程的所有点的查询:
SELECT json_agg(
json_build_object(
'tripId', trip_log_id,
'trackId', id,
'recorded_at', created_at,
'latitude', latitude,
'longitude', longitude
)
) as trips
FROM data_tracks
GROUP by trip_log_id;
及其输出:
[
[
{
"trip_log_id": 91,
"recorded_at": "2018-10-05T14:11:44.847",
"latitude": 52.5242370846803,
"longitude": 13.3443558528637
},
{
"trip_log_id": 91,
"recorded_at": "2018-10-05T14:11:44.911",
"latitude": 52.5242366166393,
"longitude": 13.3443558656828
}
],
[
{
"trip_log_id": 90,
"recorded_at": "2018-10-05T13:28:24.452",
"latitude": 52.5242370846803,
"longitude": 13.3443558528637
},
{
"trip_log_id": 90,
"recorded_at": "2018-10-05T13:28:24.489",
"latitude": 52.5242366166393,
"longitude": 13.3443558656828
}
]
]
目标
现在我需要合并这两个结果,以便每个行程 ID 都有一个 JSON 对象,其中包含问答对(键:"crowdsourcing";数组)和点行程(键:"trip";数组)。下面举个例子:
[
{ // DATA FOR TRIP 1
"crowdsourcing": [
{
"question": "Bitte bewerten Sie die Sicherheit der Radroute!",
"answeringOption": [
"Sehr sicher",
"Eher sicher",
"Neutral",
"Eher unsicher",
"Sehr unsicher"
],
"answer": "2"
},
{
"question": "Würden Sie die gefahrene Route anderen Radfahrenden weiterempfehlen?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "1"
}
],
"trip": [
{
"recorded_at": "2018-10-11T15:16:33",
"latitude": 52.506785999999998,
"longitude": 13.398065000000001
},
{
"recorded_at": "2018-10-11T15:16:32.969",
"latitude": 52.50647,
"longitude": 13.397856000000001
},
{
"recorded_at": "2018-10-11T15:16:32.936",
"latitude": 52.506166,
"longitude": 13.397593000000001
}
]
},
{ // DATA FOR TRIP 2
"crowdsourcing": [
{
"question": "Bitte bewerten Sie die Sicherheit der Radroute!",
"answeringOption": [
"Sehr sicher",
"Eher sicher",
"Neutral",
"Eher unsicher",
"Sehr unsicher"
],
"answer": "2"
}
],
"trip": [
{
"recorded_at": "2018-10-11T15:33:33.971999",
"latitude": 52.506785999999998,
"longitude": 13.398065000000001
},
{
"recorded_at": "2018-10-11T15:33:33.929",
"latitude": 52.50647,
"longitude": 13.397856000000001
}
]
}
]
方法
我创建了一个查询,请参阅DB Fiddle。但是,它 returns 在两个数组中重复记录(问题-答案对,旅行点)。我以为它必须对 JOIN
做些什么,但我的所有试验都失败了。
在您的子查询中,您已将 trip_log_id
包含在 json 部分中。但是如果你把它们作为单独的列,你将有机会加入这两个部分来反对它:
SELECT
json_agg(
json_build_object('crowdsourcing', cs.json_agg, 'trip', t.json_agg)
)
FROM
(
SELECT
trip_log_id, -- 1
json_agg(
json_build_object('question', question, 'answeringOption', "answeringOptions", 'answer', answer)
)
FROM
crowd_sourcing_answers csa
JOIN crowd_sourcing_questions csq ON csa.crowd_sourcing_question_id = csq.id
GROUP BY trip_log_id
) cs
JOIN -- 2
(
SELECT
trip_log_id, -- 1
json_agg(
json_build_object('recorded_at', created_at, 'latitude', latitude, 'longitude', longitude)
)
FROM data_tracks
GROUP by trip_log_id
) t
USING (trip_log_id) -- 2
- 滚出去
trip_log_id
- 用它来加入
另外:请注意,在 postgres 中,所有列名都不应包含任何大写字母。我建议将 addionalOptions
重命名为 additional_options
之类的名称。这样就不需要额外的 "
个字符。
我正在努力处理以下 SQL 查询:
有一个tabledata_tracks,坐标描述了一次旅行。每个行程都由 trip_log_id 唯一标识。到达旅行目的地后,用户需要参与调查。调查的答案存储在tablecrowd_sourcing_answers中。每个答案属于一个问题,位于tablecrowd_sourcing_questions.
我写了两个 SQL 查询 - 一个获取旅行的所有积分 JSON,另一个获取所有问答对:
获取旅行的所有问答对的查询:
SELECT json_agg(answer_single_trip)
FROM (SELECT json_agg(
json_build_object(
'tripId', trip_log_id,
'question', qt.question,
'answeringOption', qt."answeringOptions",
'answer', at.answer
)
) as crowdsourcing
FROM crowd_sourcing_questions as qt
INNER JOIN crowd_sourcing_answers as at ON at.crowd_sourcing_question_id = qt.id
GROUP BY trip_log_id) answer_single_trip;
及其输出:
[
{
"crowdsourcing": [
{
"tripId": 92,
"question": "Gab es auf der Strecke teilweise schlecht befahrbare Streckenabschnitte?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "2"
}
]
},
{
"crowdsourcing": [
{
"tripId": 91,
"question": "Gab es auf der Strecke teilweise schlecht befahrbare Streckenabschnitte?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "1"
}
]
},
{
"crowdsourcing": [
{
"tripId": 90,
"question": "Gab es auf der Strecke teilweise schlecht befahrbare Streckenabschnitte?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "0"
}
]
}
]
获取属于一个行程的所有点的查询:
SELECT json_agg(
json_build_object(
'tripId', trip_log_id,
'trackId', id,
'recorded_at', created_at,
'latitude', latitude,
'longitude', longitude
)
) as trips
FROM data_tracks
GROUP by trip_log_id;
及其输出:
[
[
{
"trip_log_id": 91,
"recorded_at": "2018-10-05T14:11:44.847",
"latitude": 52.5242370846803,
"longitude": 13.3443558528637
},
{
"trip_log_id": 91,
"recorded_at": "2018-10-05T14:11:44.911",
"latitude": 52.5242366166393,
"longitude": 13.3443558656828
}
],
[
{
"trip_log_id": 90,
"recorded_at": "2018-10-05T13:28:24.452",
"latitude": 52.5242370846803,
"longitude": 13.3443558528637
},
{
"trip_log_id": 90,
"recorded_at": "2018-10-05T13:28:24.489",
"latitude": 52.5242366166393,
"longitude": 13.3443558656828
}
]
]
目标
现在我需要合并这两个结果,以便每个行程 ID 都有一个 JSON 对象,其中包含问答对(键:"crowdsourcing";数组)和点行程(键:"trip";数组)。下面举个例子:
[
{ // DATA FOR TRIP 1
"crowdsourcing": [
{
"question": "Bitte bewerten Sie die Sicherheit der Radroute!",
"answeringOption": [
"Sehr sicher",
"Eher sicher",
"Neutral",
"Eher unsicher",
"Sehr unsicher"
],
"answer": "2"
},
{
"question": "Würden Sie die gefahrene Route anderen Radfahrenden weiterempfehlen?",
"answeringOption": [
"Ja",
"Nein"
],
"answer": "1"
}
],
"trip": [
{
"recorded_at": "2018-10-11T15:16:33",
"latitude": 52.506785999999998,
"longitude": 13.398065000000001
},
{
"recorded_at": "2018-10-11T15:16:32.969",
"latitude": 52.50647,
"longitude": 13.397856000000001
},
{
"recorded_at": "2018-10-11T15:16:32.936",
"latitude": 52.506166,
"longitude": 13.397593000000001
}
]
},
{ // DATA FOR TRIP 2
"crowdsourcing": [
{
"question": "Bitte bewerten Sie die Sicherheit der Radroute!",
"answeringOption": [
"Sehr sicher",
"Eher sicher",
"Neutral",
"Eher unsicher",
"Sehr unsicher"
],
"answer": "2"
}
],
"trip": [
{
"recorded_at": "2018-10-11T15:33:33.971999",
"latitude": 52.506785999999998,
"longitude": 13.398065000000001
},
{
"recorded_at": "2018-10-11T15:33:33.929",
"latitude": 52.50647,
"longitude": 13.397856000000001
}
]
}
]
方法
我创建了一个查询,请参阅DB Fiddle。但是,它 returns 在两个数组中重复记录(问题-答案对,旅行点)。我以为它必须对 JOIN
做些什么,但我的所有试验都失败了。
在您的子查询中,您已将 trip_log_id
包含在 json 部分中。但是如果你把它们作为单独的列,你将有机会加入这两个部分来反对它:
SELECT
json_agg(
json_build_object('crowdsourcing', cs.json_agg, 'trip', t.json_agg)
)
FROM
(
SELECT
trip_log_id, -- 1
json_agg(
json_build_object('question', question, 'answeringOption', "answeringOptions", 'answer', answer)
)
FROM
crowd_sourcing_answers csa
JOIN crowd_sourcing_questions csq ON csa.crowd_sourcing_question_id = csq.id
GROUP BY trip_log_id
) cs
JOIN -- 2
(
SELECT
trip_log_id, -- 1
json_agg(
json_build_object('recorded_at', created_at, 'latitude', latitude, 'longitude', longitude)
)
FROM data_tracks
GROUP by trip_log_id
) t
USING (trip_log_id) -- 2
- 滚出去
trip_log_id
- 用它来加入
另外:请注意,在 postgres 中,所有列名都不应包含任何大写字母。我建议将 addionalOptions
重命名为 additional_options
之类的名称。这样就不需要额外的 "
个字符。