简体   繁体   English

为什么 PostGIS 将所有点堆叠在一起? (使用 ST_DWithin 查找半径 1000m 内的所有结果)

[英]Why is PostGIS stacking all points on top of each other? (Using ST_DWithin to find all results within 1000m radius)

New to PostGIS/PostgreSQL...any help would be greatly appreciated! PostGIS/PostgreSQL 的新手...任何帮助将不胜感激!

I have two tables in a postgres db aliased as gas and ev.我在 postgres 数据库中有两个表,别名分别为 gas 和 ev。 I'm trying to choose a specific gas station (gas.site_id=11949) and locate all EV/alternative fuel charging stations within a 1000m radius.我正在尝试选择一个特定的加油站 (gas.site_id=11949) 并在 1000m 半径内找到所有 EV/替代燃料充电站。 When I run the following though, PostGIS returns a number of ev stations that are all stacked on top of each other in the map (see screenshot).但是,当我运行以下命令时,PostGIS 会返回许多在地图中堆叠在一起的 ev 站(请参见屏幕截图)。

Anyone have any idea why this is happening?任何人都知道为什么会这样? How can I get PostGIS to visualize the points within a 1000m radius of the specified gas station?如何让 PostGIS 可视化指定加油站 1000m 半径内的点?

with myplace as (
  SELECT gas.geom 
  from nj_gas gas 
  where gas.site_id = 11949 limit 1)
select myplace.*, ev.* 
from alt_fuel ev, myplace 
where ST_DWithin(ev.geom1, myplace.geom, 1000)

在此处输入图片说明

The function ST_DWithin does not compute distances in meters using geometry typed parameters.函数ST_DWithin不使用geometry类型参数计算以米为单位的距离。

From the documentation:从文档:

For geometry: The distance is specified in units defined by the spatial reference system of the geometries.对于几何:距离以几何空间参考系统定义的单位指定。 For this function to make sense, the source geometries must both be of the same coordinate projection, having the same SRID.为了使此函数有意义,源几何图形必须具有相同的坐标投影,具有相同的 SRID。

So, if you want compute distances in meters you have to use the data type geography :因此,如果您想以米为单位计算距离,则必须使用数据类型geography

For geography units are in meters and measurement is defaulted to use_spheroid=true, for faster check, use_spheroid=false to measure along sphere.对于地理单位以米为单位,测量默认为 use_spheroid=true,为了更快检查,use_spheroid=false 沿球体测量。

That all being said, you have to cast the data type of your geometries.话虽如此,您必须转换几何的数据类型。 Besides that your query looks just fine - considering your data is correct :-)除此之外,您的查询看起来还不错-考虑到您的数据是正确的:-)

WITH myplace as (
  SELECT gas.geom 
  FROM nj_gas gas 
  WHERE gas.site_id = 11949 LIMIT 1)
SELECT myplace.*, ev.* 
FROM alt_fuel ev, myplace 
WHERE ST_DWithin(ev.geom1::GEOGRAPHY, myplace.geom::GEOGRAPHY, 1000)

Sample data:样本数据:

CREATE TABLE t1 (id INT, geom GEOGRAPHY);
INSERT INTO t1 VALUES (1,'POINT(-4.47 54.22)');

CREATE TABLE t2 (geom GEOGRAPHY);
INSERT INTO t2 VALUES ('POINT(-4.48 54.22)'),('POINT(-4.41 54.18)');

Query询问

WITH j AS (
  SELECT geom FROM t1 WHERE id = 1 LIMIT 1)
SELECT ST_AsText(t2.geom) 
FROM j,t2 WHERE ST_DWithin(t2.geom, j.geom, 1000);

     st_astext      
--------------------
 POINT(-4.48 54.22)
(1 Zeile)

You are cross joining those tables and have PostgreSQL return the cartesian product of both when selecting myplace.* & ev.* .您正在交叉加入这些表,并让 PostgreSQL 在选择myplace.* & ev.*时返回两者的笛卡尔积。

So while there is only one row in myplace , its geom will be merged with every row of alt_fuel (ie the result set will have all columns of both tables in every possible combination of both);因此,虽然myplace只有一行, myplace它的geom将与alt_fuel每一行合并(即结果集将在两者每种可能组合中包含两个表的所有列); since the result set thus has two geometry columns , your client application likely chooses either the first, or the one called geom (as opposed to alt_fuel.geom1 ) to display!由于结果集因此有两个几何列,您的客户端应用程序可能会选择第一个或名为geom (而不是alt_fuel.geom1 )的列来显示!

I don't see that you are interested in myplace.geom in the result set anyway, so I suggest to run我看不出你对结果集中的myplace.geom感兴趣,所以我建议运行

WITH
  myplace as (
    SELECT gas.geom 
    FROM   nj_gas gas 
    WHERE  gas.site_id = 11949
    LIMIT  1
  )

SELECT ev.* 
FROM   alt_fuel AS ev
JOIN   myplace AS mp
  ON   ST_DWithin(ev.geom1, mp.geom, 1000)  -- ST_DWithin(ev.geom1::GEOGRAPHY, mp.geom::GEOGRAPHY, 1000)
;

If, for some reason, you also want to display myplace.geom along with the stations, you'd have to UNION[ ALL] the above with a SELECT * on myplace ;如果出于某种原因,您还想将myplace.geom与站一起显示,则必须在myplace上使用SELECT *对上述内容进行UNION[ ALL] note that you will also have to provide the same column list and structure (same data types!) as alt_fuel.* (or better, the other side of the UNION[ ALL] ) in that SELECT !请注意,您还必须在该SELECTalt_fuel.*相同的列列表和结构(相同的数据类型!)(或者更好, UNION[ ALL]另一侧)!


Note the suggestions made by @JimJones about units;请注意@JimJones关于单位的建议 if your data is not projected in a meter based CRS (but in a geographic reference system ; 'LonLat'), use the cast to GEOGRAPHY to have ST_DWithin consider the input as meter (and calculate using spheroidal algebra instead of planar (Euclidean))!如果您的数据不是在基于的 CRS 中投影的(而是在地理参考系统中;“LonLat”),请使用GEOGRAPHY ST_DWithin转换让ST_DWithin将输入视为(并使用球体代数而不是平面(欧几里得)进行计算) !

Resolved by using:通过使用解决:

WITH
  myplace as (
    SELECT geom as g
    FROM   nj_gas  
    WHERE  site_id = 11949 OR site_id = 11099 OR site_id = 11679 or site_id = 480522
  ), myresults AS (
SELECT ev.* 
FROM   alt_fuel AS ev
JOIN   myplace AS mp
  ON   ST_DWithin(ev.geom, mp.g, 0.1))
select * from myresults```

Thanks so much for your help @ThingumaBob and @JimJones ! Greatly appreciate it.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Postgis ST_DWithin匹配特定半径AND右边的点 - Postgis ST_DWithin match a certain radius AND points on the right 使用填充有PostGIS WKB坐标的Postgres array []会导致“函数st_dwithin(文本,几何,整数)不是唯一的” - Using a Postgres array[] filled with PostGIS WKB coordinates results in “function st_dwithin(text, geometry, integer) is not unique” BigQuery ST_DWITHIN 多点与多点 - BigQuery ST_DWITHIN multiple points with multiple points 按结果出现的半径数将结果按ST_DWith排序 - Rank order ST_DWithin results by the number of radii a result appears in 如何使用ST_DWithin查找近点? - How to use ST_DWithin to find near point? 在PostgreSQL上使用PostGIS扩展,为什么`ST_ConvexHull`不包含所有创建它的点? - Using PostGIS extensions on PostgreSQL, why doesn't `ST_ConvexHull` contain all points that create it? SQL Geometry 查找半径内的所有点 - SQL Geometry find all points in a radius 比较数据以显示彼此相差1000的结果 - Compare data to display results within 1000 of each other 选择POINT()的100米半径内的所有点 - Select all points that are within a 100 metre radius of a POINT() 基于st_dwithin条件的BigQuery Left Join就像一个内部联接 - BigQuery Left Join based on st_dwithin condition acting like an Inner Join
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM