특정 위도 / 경도의 30km 반경 내에있는 모든 결과를 반환 하시겠습니까?


21

the_geom비슷한 데이터가 포함 된 열이있는 테이블 이 있습니다.

0103000020E61000000100000005000000CE473AACFA071E40F27FB23340744740336FE841C6231E40873BED903F744740FC150A0ACE231E40D19E2684637647409C9B443D00081E409A9AF82664764740CE473AACFA071E40F27FB23340744740

함수를 적용하면 다음을 ST_AsEWKT(the_geom)반환합니다.

SRID=4326;POLYGON((7.5077921782085 46.9082092877942,7.53493597966353 46.9081898840296,7.53496566473541 46.9249119938446,7.50781341296434 46.9249314035307,7.5077921782085 46.9082092877942))

특정 위도 / 경도의 30km 반경 내에있는 모든 데이터를 선택해야합니다. 예를 들면 다음과 같습니다.

  • 위도 = 46.8167
  • Lng = 6.9333

그러나을 사용하려고 할 때마다 ST_Distance()항상 1보다 작은 값을 받았으며를 사용하면 ST_DWithin()항상 true를 반환했습니다.

답변:


23

특정 거리 내에서 데이터를 얻으려면 PostgreSQL에 대한 다음 쿼리를 확인하십시오. 도움이 되길 바랍니다.

SELECT *
FROM your_table
WHERE ST_Distance_Sphere(the_geom, ST_MakePoint(your_lon,your_lat)) <= radius_mi * 1609.34

1
그것을 사용할 수있었습니다 : SELECT * FROM myTable WHERE GeometryType (ST_Centroid (the_geom)) = 'POINT'AND ST_Distance_Sphere (ST_Point (ST_X (ST_Centroid (the_geom))), ST_Y (ST_Centroid (the_geom))), (ST_MakePoint (6.9333 , 46.8167))) <= 18 * 1609.34
dan2k3k4

훌륭합니다 :)
Farhat Abbas

2
다른 궁금한 점이 있다면 1609.34 숫자는 마일 당 미터이며 postgres가 사용하는 기본 단위입니다. 킬로미터를하려면 분명히 1000을 곱하십시오.
1mike12

2
Pedantic 참고 : 정확히 1609.344입니다 (정의에 따라)
barrycarter

6

지리 열이 아닌 지오메트리 열에 지오메트리를 저장하는 것처럼 들립니다. ST_Distance
함수 는 항상 미터 대신 프로젝션 단위로 측정 값을 반환합니다. 귀하의 경우 (4326), 그것은 도가 될 것입니다. ST_Buffer 도 각도로 측정 되므로 ST_Within과 함께 버퍼를 사용하면 작동하지 않습니다 .

지오메트리 대신 지리를 사용하도록 데이터를 변환하거나 포인트를 미터, 버퍼를 사용하는 투영으로 변환 한 다음 4326으로 ​​다시 변환하여 그 안에 무엇이 있는지 확인할 수 있습니다.

SELECT
    *
FROM <your data>
WHERE ST_Within(the_geom, 
                ST_Transform(ST_Buffer(ST_Transform(ST_SetSRID(ST_MakePoint(6.9333, 46.8167), 4326), 3857), 30000), 4326)) = 1

이 점 은 웹 맵에서 인기있는 프로젝션 인 3857 로 포인트를 투영합니다. 그런 다음 30,000 미터로 버퍼링 한 다음 ST_Within으로 전달하기 전에 다시 4326으로 ​​다시 투영합니다.


의사-메이커가 거리에 대해 신뢰할 수 없다는 점을 제외하면 데이터가 적도에 가까이 있지 않으면 특히 30km 거리에서 결과가 사라집니다.
Vince

6

내 세계에서는 다음과 같은 사용자 지정 SRID (Google지도 용)를 사용했습니다.

SELECT * FROM addresses WHERE ST_DWithin(location, ST_SetSRID(ST_MakePoint(longitude, latitude), 3785), radius);

유형이 어디 location기하학 (포인트, 3785)에, 그리고 longitude, latituderadius플로트있다 (예를 들면 -100, 44, 100W / 44N / 30 "단위"는 30 - 아래 참조)

다른 객체의 반경 내에서 모든 객체를 찾는 가장 좋은 방법무엇입니까?를 참조하십시오 . postgis 문서에서 :

ST_DWithin(geometry, geometry, distance)기능은 인덱스 거리 검색을 수행하는 편리한 방법입니다. 거리 반경을 둘러싸기에 충분한 검색 사각형을 만든 다음 색인 된 결과 하위 집합에서 정확한 거리 검색을 수행합니다.

업데이트 : 단위는 SRID 3785의 마일이 아닙니다 ... 라디안 또는도 또는 그와 비슷한 것으로 보입니다. 그러나 내 SRID의 사양에 따르면 단위는 미터 또는도이며 적어도 일부 변환 없이는 아닙니다.

alex=# select * from spatial_ref_sys where srid=3785; srid | auth_name | auth_srid | srtext | proj4text
3785 | EPSG | 3785 | PROJCS["Popular Visualisation CRS / Mercator (deprecated)",GEOGCS["Popular Visualisation CRS",DATUM["Popular_Visualisation_Datum",SPHEROID["Popular Visualisation Sphere",6378137,0,AUTHORITY["EPSG","7059"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6055"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4055"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3785"],AXIS["X",EAST],AXIS["Y",NORTH]] | +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs


3785 (게시물)와 3857의 차이는 무엇입니까?
조정

그들은 다른 전망입니다. 38753857 - 하나가 다른 것보다 더 나은 경우 나도 몰라
AlexChaffee

1
"EPSG 3785는 다른 EPSG 3857을 선호하여 더 이상 사용되지 않습니다" -github.com/rgeo/rgeo/pull/61
Yarin

2

나는 이것이 효과가 있다고 생각한다.

SELECT gid FROM table 
WHERE ST_DWithin(the_geom, ST_SetSRID(ST_Point(6.9333, 46.8167), 4326), 30000)

3
the_geom을 지리로 캐스팅하면 작동합니다. st_dwithin (geography (the_geom), geography (<Point, 4326>), 30000)
cavila
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.