Postgresql Postgis SQL Complex Join (не обязательно, однако, связанный с ГИС) - PullRequest
0 голосов
/ 18 сентября 2018

Извините за отсутствие блеска, но это трудно описать ...

Позвольте мне сказать, что у меня есть две таблицы (cad и cad_polygon) ...

cad и cad_polygonиспользовать тот же столбец, который относится друг к другу (cad_pid) ...

cad имеет следующие столбцы: cad_pid, jrsdctn_id

, а cad_polygon содержит следующие столбцы: cad_pid, ogc_fid, wkb_geometry

Теперь, мой нижеприведенный запрос (пытаясь полдня) выбирает участок на основе градуса из длинной латинской координаты, из этого значительно меньшего подмножества полигонов, он находит их расстояние в метрах от заданногоlong, координата lat, затем отображает только многоугольники, центр тяжести которых находится в пределах 500 м от координаты long, lat.

SELECT SUBQUERY.cad_pid, SUBQUERY.ogc_fid, SUBQUERY.dist_meters,
    SUBQUERY.wkb_geometry FROM (
    SELECT cad_pid, ogc_fid,
    CAST(ST_Distance_Sphere(
        ST_Centroid(wkb_geometry),
            ST_GeomFromText(
                'POINT(00.0000 -00.0000)',
            900914)
        ) AS numeric
    ) AS dist_meters, wkb_geometry
    FROM cad_polygon
    WHERE ST_DWithin(
        ST_Centroid(wkb_geometry),
        ST_GeomFromText(
            'POINT(00.0000 -00.0000)',
        900914),
    0.01)
    ORDER BY dist_meters ASC
) AS SUBQUERY
WHERE SUBQUERY.dist_meters < 500;

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

Пример данных будет: cad:

cad_pid | jrsdctn_id
0001    | abc123
0002    | def456
0003    | dhk778
0004    | dsk730


cad_polygon:

cad_pid | ogc_fid | wkb_geometry
0001    | ht0101  | 67686687601010000200063D7987FF15ASD1518541DAW
0002    | hz4561  | 435453457601010000200063D7987FF15ASDFW4GF8DE4
0003    | yv0301  | 2626WD687601010000200063D7987FF15ASD1WE851D4D
0004    | vt9701  | D484DW4D8441D8W1C684V63D7987FF15ASD1D7DW4848D

Ожидаемые результаты:

cad_pid | jtsdctn_id | ogc_fid | dist_meters | wkb_geometry
0002    | def456     | hz4561  | 192.769     | 43545...
0004    | dsk730     | vt9701  | 342.548     | D484D...

Если какой-нибудь sql wizЯ могу помочь, было бы здорово!

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Немного поздно, и принятый ответ абсолютно верен в отношении JOIN, конечно, но на самом деле это в значительной степени связано с ГИС , и его осознание в конечном счете облегчает вам задачу:

Похоже, вы либо используете пользовательскую CRS, либо ogr2ogr (или любую функцию GDAL / OGR) не нашли соответствующий SRID / проекцию в PostGIS 'atial_ref_sys таблице;однако любая функция PostGIS, использующая LonLat в качестве входных данных для сферической / шпероидальной алгебры, всегда будет предполагать, что ваши координаты находятся в EPSG: 4326 (WGS84).

Если ваши LonLat не точно совпадает с результатами WGS84, результаты будут отключены!

Теперь PostGIS также имеет тип geography , который снова принимает EPSG: 4326 координат, которые будут, если используются сэти функции неявно используют meter в качестве единиц измерения и будут рассчитываться на сфероиде WGS84, если используются параметры по умолчанию ST_Distance (более точные, но немного медленнее, чем с use_spheroid := false, которые будут вычислять расстояние на основевместо сферы).

Имея это в виду, ваш запрос может быть выражен следующим образом:

WITH
  pt AS (
    SELECT ST_Transform(ST_SetSRID(ST_MakePoint(0, 0), 900914), 4326)::geography AS geog
  ),

  ctr AS (
    SELECT *,
           ST_Transform(ST_Centroid(wkt_geometry), 4326)::geography AS geog
    FROM cad_polygon
  )

SELECT ctr.cad_pid,
       cad.jtsdctn_id,
       ctr.ogr_fid,
       ST_Distance(ctr.geog, pt.geog) AS distance_meter,
       ctr.wkt_geometry
FROM ctr
JOIN cad
  ON ctr.cad_pid = cad.cad_pid
WHERE ST_DWithin(ctr.geog, pt.geog, 500)
ORDER BY distance_meter ASC;

Обратите внимание на использование CTE, чтобы избежать преобразования / приведения для каждой обработанной строки и сделать вещиболее структурированный.

Я просто не мог отпустить это ...

0 голосов
/ 18 сентября 2018

Вы можете использовать JOIN

    SELECT SUBQUERY.cad_pid, SUBQUERY.ogc_fid, SUBQUERY.dist_meters,
        SUBQUERY.wkb_geometry, SUBQUERY.jrsdctn_id FROM (
        SELECT cad_pid, ogc_fid,
        CAST(ST_Distance_Sphere(
            ST_Centroid(wkb_geometry),
                ST_GeomFromText(
                    'POINT(00.0000 -00.0000)',
                900914)
            ) AS numeric
        ) AS dist_meters, wkb_geometry, cad.jrsdctn_id
        FROM cad_polygon
        INNER JOIN cad on cad.cad_pid = cad_polygon.cad_pid

        WHERE ST_DWithin(
            ST_Centroid(wkb_geometry),
            ST_GeomFromText(
                'POINT(00.0000 -00.0000)',
            900914),
        0.01)
        ORDER BY dist_meters ASC
    ) AS SUBQUERY
    WHERE SUBQUERY.dist_meters < 500;

или лучше добавить соединение во внешнюю

SELECT SUBQUERY.cad_pid
        , SUBQUERY.ogc_fid
        , SUBQUERY.dist_meters,
        SUBQUERY.wkb_geometry, cad.jrsdctn_id 
    FROM (
        SELECT cad_polygon.cad_pid, ogc_fid,
        CAST(ST_Distance_Sphere(
            ST_Centroid(wkb_geometry),
                ST_GeomFromText(
                    'POINT(00.0000 -00.0000)',
                900914)
            ) AS numeric
        ) AS dist_meters
        , wkb_geometry
        FROM cad_polygon
        WHERE ST_DWithin(
            ST_Centroid(wkb_geometry),
            ST_GeomFromText(
                'POINT(00.0000 -00.0000)',
            900914),
        0.01)
        ORDER BY dist_meters ASC
    ) AS SUBQUERY
    INNER JOIN cad on cad.cad_pid = SUBQUERY.cad_pid
    WHERE SUBQUERY.dist_meters < 500;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...