[英]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
!请注意,您还必须在该
SELECT
与alt_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.