PostGIS Geometry Query ส่งคืน“ ข้อผิดพลาด: การดำเนินการกับรูปแบบ SRID ผสม” สำหรับค่าบางค่าเท่านั้น


17

ฉันมีตาราง PostGIS พร้อมคอลัมน์รูปทรงเรขาคณิตสองคอลัมน์ทั้งสองกำหนดด้วย SRID 4326 ฉันสามารถแทรกลงในตารางโดยไม่มีปัญหาโดยใช้INSERTคำสั่งต่อไปนี้(โดยที่lngและlatเป็นค่าที่ส่งผ่านโดยทางโปรแกรม):

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)
);

ฉันได้ตรวจสอบด้วยว่ามี SRID เพียงประเภทเดียวใน geometry_columns:

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 ก็จะผสมและ0 4326นี่เป็นข้อผิดพลาดที่มีประโยชน์หากการอ้างอิงเชิงพื้นที่แตกต่างกันอย่างแท้จริง ในกรณีของคุณ SRID นั้นเหมือนกัน แต่คุณไม่ได้เข้ารหัส SRID ไปยังจุดสอบถาม ดังนั้นในการแก้ไขแบบสอบถามของคุณจะระบุ SRID ที่เหมือนกันเสมอสำหรับจุดสอบถามของคุณและพวกเขาจะไม่ถูกผสมอีกต่อไป

ตามบันทึกข้าง, ประเภทมี SRID เริ่มต้นของ 4326 (WGS 84) ดังที่แสดงไว้ที่นี่:geography

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

ดังนั้นถ้าคุณใช้geographyชนิดแทนgeometryชนิด SRID ไม่จำเป็นต้องระบุ (เว้นแต่คุณต้องการ SRID ที่แตกต่างกันสำหรับ ellipsoid ทางเลือกสำหรับ Mars หรืออะไรก็ตาม)


สำหรับสาเหตุที่คิวรีหนึ่งมีข้อผิดพลาดและอันอื่น ๆ ก็ไม่ได้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_GeomFromTextเพียงเพราะฉันไม่รู้วิธีอื่นในการระบุ SRID ... ?) มีวิธีตั้งค่า SRID เริ่มต้นสำหรับการสืบค้นหรือไม่ ดูเหมือนว่าค่อนข้างจะตั้งอย่างชัดเจนในแต่ละครั้ง อีกครั้งขอบคุณ!
jessykate

1
ฉันได้อัปเดตคำตอบเพื่อแนะนำการใช้geographyประเภทซึ่งมักจะเป็น 4326 นอกจากนี้ยังมีหลายวิธีในการระบุ SRID
Mike T

0

ข้อสังเกตสองประการที่อาจช่วยได้: ข้อแรกPoint(Double, Double)คือฟังก์ชัน PostgreSQL ดั้งเดิมที่คุณบังคับใช้กับชนิดข้อมูล PostGIS ST_MakePoint(double x, double y)จะสร้างรูปทรงเรขาคณิตที่เหมาะสม นอกจากนี้ในคำถามของคุณคุณดูเหมือนจะอ้างถึงอาร์กิวเมนต์ที่สองเป็นลองจิจูด การสั่งซื้อที่เหมาะสมเป็นสิ่งซึ่งสอดคล้องกับx, y Longitude, Latitudeการรับสิ่งที่ตรงกันข้ามสามารถส่งคืนผลลัพธ์ที่คาดไม่ถึงโดยไม่ทิ้งข้อยกเว้นใด ๆ

ไม่มีสิ่งใดอธิบายได้ว่าทำไมตัวอย่างแรกของคุณถึงใช้งานได้ แต่ไม่ใช่หวังว่าจะช่วยให้คุณสร้างข้อความค้นหาที่ดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.