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 部分中。但是如果你把它们作为单独的列,你将有机会加入这两个部分来反对它:

demo: db<>fiddle

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      
  1. 滚出去trip_log_id
  2. 用它来加入

另外:请注意,在 postgres 中,所有列名都不应包含任何大写字母。我建议将 addionalOptions 重命名为 additional_options 之类的名称。这样就不需要额外的 " 个字符。