ВЫБРАТЬ из функции, которая возвращает несколько столбцов - PullRequest
0 голосов
/ 25 февраля 2019

У меня есть следующий запрос, который определяет расположение кластеров и возвращает идентификатор кластера, а также структуру, содержащую исходные точки в этом кластере:

SELECT
    cluster_id,
    ST_AsGeoJSON(ST_Collect(origin)) AS points
FROM (
    SELECT
        origin,
        ST_ClusterDBSCAN(origin, eps := 0.01, minPoints := 5) OVER(ORDER BY id) AS cluster_id
    FROM
        ride
    WHERE
        region_id = 1 AND
        created_at > now() - interval '1 week'
) a
WHERE cluster_id IS NOT NULL
GROUP BY cluster_id

Пример вывода:

3   {"type":"MultiPoint","coordinates":[ ... ]}
4   {"type":"MultiPoint","coordinates":[ ... ]}

Вместо того, чтобы возвращать необработанные точки, я хочу вернуть ограничивающий круг для кластера (центр и радиус), что можно сделать с помощью ST_MinimumBoundingRadius:

SELECT
    ST_AsGeoJSON(center),
    radius
FROM
    ST_MinimumBoundingRadius(
        ST_GeomFromGeoJSON('{"type":"MultiPoint","coordinates":[ ... ]}')
    )

Пример вывода:

{"type":"Point","coordinates":[ ... ]}  0.002677744742706528

Однако, поскольку ST_MinimumBoundingRadius возвращает два столбца, ниже выдается ошибка:

SELECT
    cluster_id,
    ST_MinimumBoundingRadius(ST_Collect(origin))
FROM (
    ...
) a
WHERE cluster_id IS NOT NULL
GROUP BY cluster_id;

Я нашел этот вопрос, в котором упоминается LATERAL, но я не был 'Невозможно получить рабочий запрос.

Как правильно это сделать?

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Попробуйте другой подвыбор:

SELECT q.cluster_id,
       (q.mbr).radius,
       (q.mbr).center
FROM (
   SELECT cluster_id,
          ST_MinimumBoundingRadius(
             ST_Collect(origin)
          ) AS mbr
   FROM (
      ...
   ) AS a
) AS q;
0 голосов
/ 25 февраля 2019

Действительно простой, в конце концов, не знаю, как я не догадался об этом.

SELECT
    cluster_id,
    (ST_MinimumBoundingRadius(ST_Collect(origin))).*
FROM (
    SELECT
        origin,
        ST_ClusterDBSCAN(origin, eps := 0.01, minPoints := 5) OVER(ORDER BY id) AS cluster_id
    FROM
        ride
    WHERE
        region_id = 1 AND
        created_at > now() - interval '1 week'
) a
WHERE cluster_id IS NOT NULL
GROUP BY cluster_id
...