Используйте GROUP_CONCAT () для генерации полигонов в MySQL - PullRequest
0 голосов
/ 15 мая 2018

У меня есть таблица, в которой есть столбцы zone (имя зоны, являющейся строкой), longitude (десятичное число), latitude (десятичное число), logical order (целое число).

logical_order указывает порядок, в котором координаты могут быть объединены для создания многоугольника. Например, каждая зона будет иметь несколько строк в этой таблице с разными longitude, latitude. Для каждой строки зоны logical_order начнется с 1 (для начальной точки) и увеличится на единицу на строку. Например, если зона имеет 3 точки, logical_order будет выполняться с 1 по 3. Координаты в точке 3 не совпадают с позицией 1. Другими словами, координаты не закрывают многоугольник.

Я пытаюсь создать POLYGON, группируя координаты каждой зоны и используя пространственный пакет, как показано ниже:

Я попробовал следующий запрос:

SELECT t0.zone, ST_GeometryFromText(CONCAT("'POLYGON((", GROUP_CONCAT(t0.coordinate ORDER BY t0.logical_order SEPARATOR ','), "))'")) FROM
(
    (SELECT zone, CONCAT(longitude, ' ', latitude) AS coordinate, logical_order FROM zones)
    UNION ALL
    (SELECT zone, CONCAT(longitude, ' ', latitude) AS coordinate, 1000 AS logical_order FROM zones WHERE logical_order = 1)
) t0 
GROUP BY t0.zone

Однако, это дает мне ошибку:

Error Code: 3037. Invalid GIS data provided to function st_geometryfromtext.

Как я могу исправить эту ошибку? Я иду по правильному пути?

EDIT:

Если я попробую без ST_GeometryFromText() во втором запросе, я получу строку вроде:

POLYGON(77.5068350000 -11.4907909800,179.7363280000 -11.4907909800,179.7363280000 -60.0000000000,77.5068350000 -60.0000000000,77.5068350000 -11.4907909800)

После добавления двух скобок, как показано ниже, выдается та же ошибка:

POLYGON((77.5068350000 -11.4907909800,179.7363280000 -11.4907909800,179.7363280000 -60.0000000000,77.5068350000 -60.0000000000,77.5068350000 -11.4907909800))

РЕДАКТИРОВАТЬ 2:

Я также вручную проверил одну за другой для каждой зоны закрытие многоугольника, что нормально. Я также увеличил ограничение на количество символов group_concat(). Но ошибка все еще сохраняется.

РЕДАКТИРОВАТЬ 3:

Скрипка SQL с примерами данных: http://www.sqlfiddle.com/#!9/5094e5/5

1 Ответ

0 голосов
/ 15 мая 2018

На этот вопрос ответил ypercubeᵀᴹ в db exchange. Вы можете обратиться к фактическому ответу и обсуждению здесь .

Было несколько проблем:

  1. Значение по умолчанию для количества символов group_concat_max_len было слишком мало, обрезая некоторые координаты
  2. Двойные кавычки, используемые во внешних CONCAT(), вызывали проблемы. Необходимо использовать одинарные кавычки
  3. То, как я закрыл полигон с помощью GROUP BY, было сомнительно.

Для будущих пользователей я напишу ответ здесь:

Вероятно, ошибка вызвана тем, что «цикл» не замкнут, то есть последняя точка в многоугольнике не совпадает с первой.

Это может быть из двух вопросов:

Решение: увеличьте его либо на уровне сервера, либо на уровне сеанса.

  • подверженный ошибкам GROUP BY, используемый для добавления дополнительной точки.

Используемая вами GROUP BY склонна давать неверные результаты, поскольку она не всегда может выбрать нужную строку (WHERE logical_order = 1) для чтения координат:

(
    SELECT zone, 
           CONCAT(longitude, ' ', latitude) AS coordinate, 
           logical_order 
    FROM zones
    UNION
    -- This is to close the polygon by adding the first coordinate also 
    -- as the final coordinate of the zone. 
    SELECT zone, 
           CONCAT(longitude, ' ', latitude) AS coordinate, 
           COUNT(zone) + 1 AS logical_order 
    FROM zones 
    GROUP BY zone
) t0 

Я бы написал так:

(
    SELECT zone, 
           CONCAT(longitude, ' ', latitude) AS coordinate, 
           logical_order 
    FROM zones
    UNION ALL
    -- This is to close the polygon by adding the first coordinate also
    -- as the final coordinate of the zone. 
    SELECT zone, 
           CONCAT(longitude, ' ', latitude), 
           1000000     -- unlikely to have a million points polygon
    FROM zones
    WHERE logical_order = 1
) t0 

Окончательный рабочий запрос:

SELECT t0.zone, ST_GeometryFromText(CONCAT('POLYGON((', GROUP_CONCAT(t0.coordinate ORDER BY t0.logical_order SEPARATOR ','), '))')) FROM
(
    (SELECT zone, CONCAT(longitude, ' ', latitude) AS coordinate, logical_order FROM zones)
    UNION
    (SELECT zone, CONCAT(longitude, ' ', latitude) AS coordinate, 10000 AS logical_order FROM zones WHERE logical_order = 1)
) t0 
GROUP BY t0.zone;

Необходимо правильно установить group_concat_max_len.

...