PostGIS 지오메트리 쿼리는 특정 값에 대해서만 "오류 : 혼합 SRID 지오메트리 작업"을 반환합니다


17

나는 SRID 4326으로 정의 모두 나는 다음과 같은 사용하여 문제없이 테이블에 삽입 할 수있는 두 개의 기하학 열이 PostGIS와 테이블이 INSERT(성명 lnglat값이 프로그램에 전달됩니다)

INSERT INTO pad_meta (
    uuid, created, updated, name, origin, radius, area, expiry, creator
) VALUES (
    $1, now(), now(), $2, ST_GeomFromText('POINT(lng, lat)', 4326), $3, 
    ST_Buffer(ST_GeomFromText('POINT(lng, lat)', 4326), $4), $5, $6
)

그러나 ST_Intersects를 사용하여 교차점을 쿼리 할 때 얻는 점의 값에 따라ERROR: Operation on mixed SRID geometries .

예를 들어이 쿼리는 다음과 같이 작동합니다.

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
) ORDER BY created DESC;

그리고 이것은 오류가 있습니다.

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 47.602634395263560)'::geometry, area::geometry 
) ORDER BY created DESC;

참고, 그들은 경도 값을 제외하고는 동일 쿼리입니다. 다른 값으로 실험했지만 작동하지 않는 쿼리 사이의 명확한 전환점을 식별하지 못했습니다.

나는 근본적으로 무언가를 오해하고 있다고 생각합니다. 지금 ST_GeomFromText은 SRID 를 사용 하고 명시 적으로 지정하도록 쿼리를 다시 형식화하여 문제를 해결 / 수정 / 해결했습니다 .

SELECT * FROM pad_meta where ST_Intersects(
    ST_GeomFromText('POINT(-122.334172173172 47.602634395263560)', 4326), area
) ORDER BY created DESC;

그러나 나는 솔직히 차이점이 무엇인지, 이것이 정말로 "솔루션"인지 이해하지 못한다.

내 질문은 : 특정 값에 대해서만 오류가 발생하는 이유는 무엇 이며이 쿼리의 형식을 지정하는 올바른 방법은 무엇입니까?

다음은 참조를위한 테이블 정의입니다.

CREATE TABLE IF NOT EXISTS pad_meta (
  uuid CHAR(32),
  created TIMESTAMP,
  updated TIMESTAMP,
  name VARCHAR(128),
  origin GEOMETRY(Point, 4326),
  radius INTEGER,
  area GEOMETRY(Polygon, 4326),
  expiry TIMESTAMP,
  creator CHAR(32),
  PRIMARY KEY (uuid)
);

또한 geometry_columns에 SRID 유형이 하나만 있음을 확인했습니다.

SELECT f_table_name, f_geometry_column, srid FROM geometry_columns;
f_table_name | f_geometry_column | srid
--------------+-------------------+------
 pad_meta     | origin            | 4326
 pad_meta     | area              | 4326

도움 / 조언 감사합니다. 감사합니다! (참고 : 이 질문 도 보았지만 테이블에 삽입 할 때 이미 지오메트리 SRID를 명시 적으로 정의했기 때문에 발생하지 않는 것 같습니다.)

답변:


24

SRID없이 지오메트리를 지정하면 실제로 0(또는-1 버전 <2)입니다.

SELECT ST_SRID('POINT(-122.334172173172 46.602634395263560)'::geometry);
 st_srid
---------
       0

당신이 SRID = 4326 또 다른 하나이 형상을 사용할 때,이 혼합되어 04326 . 공간 참조가 실제로 다른 경우 일반적으로 유용한 오류입니다. 귀하의 경우 SRID는 동일하지만 SRID를 쿼리 지점으로 인코딩하지 않았습니다. 따라서 쿼리를 수정 하려면 항상 쿼리 지점에 대해 동일한 SRID를 지정 하면 더 이상 혼합되지 않습니다.

사이드 참고로 타입은 아래와 같이, (4326)의 기본 SRID (WGS 84)를 갖는다 :geography

SELECT ST_SRID('POINT(-122.334172173172 46.602634395263560)'::geography::geometry);
 st_srid
---------
    4326

따라서 geography대신에 유형을 사용하면geometry SRID를 지정할 필요가 없습니다 (Mars 등의 다른 타원체에 대해 다른 SRID를 원하지 않는 한).


한 쿼리에 오류가 있고 다른 쿼리에 오류가있는 이유에 대해서는 ST_Intersects먼저 &&경계 상자 검색을 수행하는 것이 빠르며 SRID에 대해서는 신경 쓰지 않습니다. 경계 상자가 교차하지 않으면 혼합 된 SRID 오류 메시지가 발생하지 않습니다. 그러나 서로 교차하는 경우 두 번째 필터는 _ST_Intersects보다 정확하며 두 SRID가 일치하는지 확인하고 혼합 된 경우 오류를 발생시킵니다. 예를 들면 다음과 같습니다.

WITH pad_meta AS (
    SELECT 'SRID=4326;POLYGON((-124 50, -124 47, -121 50, -124 50))'::geometry AS area)

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
);

교차 경계 상자가 없으며 우회합니다 _ST_Intersects. 그러나 POINT(-122.334172173172 47.602634395263560)경계 상자가 겹치므로 오류가 발생합니다 (지오메트리가 실제로 교차하지 않더라도).

그러나 동일한 형상과 다른 필터를 사용하십시오.

WITH pad_meta AS (
    SELECT 'SRID=4326;POLYGON((-124 50, -124 47, -121 50, -124 50))'::geometry AS area)

SELECT * FROM pad_meta where _ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
);

경계 상자가 고려되지 않으므로 혼합 SRID 오류가 발생합니다.


와우 감사합니다. 말이 되네요 SRID=4326나머지 문장에 대해 SRID를 설정하는 올바른 방법으로 쿼리 앞에 접두사를 추가하고 있습니까? ( ST_GeomFromTextSRID를 지정하는 방법을 모르기 때문에 단순히 사용하는 것과는 달리 ...?) 쿼리에 대한 기본 SRID를 설정하는 방법이 있습니까? 매번 명시 적으로 설정하는 것이 장황한 것 같습니다. 다시 한번 감사합니다!
jessykate

1
geography항상 4326 인 유형을 사용하도록 제안하기 위해 답변을 업데이트 했습니다. 또한 SRID를 지정하는 여러 가지 방법이 있습니다 .
Mike T

0

도움이 될 수있는 몇 가지 관찰 : 하나 Point(Double, Double)는 PostGIS 데이터 형식으로 강제 변환하는 기본 PostgreSQL 함수입니다. ST_MakePoint(double x, double y)적절한 형상을 만듭니다. 또한 귀하의 질문에 두 번째 논쟁을 경도라고 부르는 것 같습니다. 올바른 순서는 x, y에 해당합니다 Longitude, Latitude. 이를 되 돌리면 예외를 발생시키지 않고 예기치 않은 결과가 반환 될 수 있습니다.

이 중 어느 것도 왜 첫 번째 예제가 다른 이유는 아니고 때로는 효과가 있는지 설명하지 않지만 좋은 쿼리를 만드는 데 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.