2011-02-02 111 views
4

我寫此查詢和它的作品,雖然這是一個有點慢:ST_Distance和「爲」在PostGIS的

SELECT name, 
(ST_Distance(ST_Transform(way,900913),ST_Transform(ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913))) 
FROM ga_osm_latlong_polygon 
WHERE 
((ST_Distance(ST_Transform(way,900913),ST_Transform(ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913))) 
<= 1000) 
ORDER BY 
(ST_Distance(ST_Transform(way,900913),ST_Transform(ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913))), 
name 

我試圖重寫它在一個更優雅的方式,用「爲」 :

SELECT name, 
(ST_Distance(ST_Transform(way,900913),ST_Transform(ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913))) AS d 
FROM ga_osm_latlong_polygon 
WHERE (d <= 1000) 
ORDER BY d, name 

不幸的是,我得到: 錯誤:列 「d」 不存在

約我越來越錯在這裏是什麼你知道嗎?

謝謝!

回答

2

Hallo Mulone

關於你的別名問題,路德是對的。

關於查詢緩慢有兩個原因。

首先,您要變換的每一點,這需要時間

其次,可能更importand,成規與空間索引一起使用ST_Dwithin而不是在where子句中使用距離。

ST_Dwithin使用空間索引來排除大量計算。

但是投射您的數據來做這些計算會給您非常不準確的答案。爲什麼不使用地理功能呢。

嘗試:

SELECT d, name 
(
    SELECT ST_Distance(a.way,b.geom) as d, a.name from 
     (SELECT way::geography, name from ga_osm_latlong_polygon) a, 
     (SELECT 'POINT(-6.2222 53.307)'::geography as geom) b 
    where ST_DWithin(a.way, b.geom, 1000) 
) c 
order by d, name; 

但我想我會寫更多的只是想:

SELECT ST_Distance(a.way,b.geom) as d, a.name from 
     (SELECT way::geography, name from ga_osm_latlong_polygon) a, 
     (SELECT 'POINT(-6.2222 53.307)'::geography as geom) b 
    where ST_DWithin(a.way, b.geom, 1000) 
order by ST_Distance(a.way,b.geom), name; 

但因爲避免ST_Distance運行兩次第一個版本可能會更快。

但是爲了得到這個效果當然你需要空間索引 現在當我寫它時,我意識到對地理位置的投射可能會成爲索引的炫目者。如果是這樣,我會建議你製作一個地理專欄,並建立一個適當的索引。工作指數在這裏像夜晚和日子一樣。

更新: 或者,也許你可以直接創建與地理類型的索引。我還沒有嘗試過,但值得一試:是這樣的:

Create index idx_polygon_geog 
on ga_osm_latlong_polygon 
using gist(way::geography); 

HTH

尼克拉斯

+0

謝謝!由於某些原因,類型'地理'沒有在我的PostGIS中定義。我需要的實際上是以米爲單位的半徑範圍內的對象(存儲在緯度/經度),這就是爲什麼我要改變mercator中的所有內容。任何其他方法呢? – Mulone 2011-02-03 10:48:50

0

列別名在WHERE子句中不可見。你可以重寫查詢,像這樣:

SELECT * FROM 
(
    SELECT name, 
      (ST_Distance( 
      ST_Transform(way,900913), 
      ST_Transform(ST_GeomFromText('POINT (-6.2222 53.307)',4326),900913))) 
     AS d 
    FROM ga_osm_latlong_polygon 
) 

AS tmp  
WHERE (d <= 1000) 
ORDER BY d, name 

另外,我不知道,如果PostGIS的可利用空間索引在你的ST_Distance()謂詞。根據當前文檔:

http://postgis.refractions.net/documentation/manual-1.5/ch04.html#id2638955

ST_Distance()包括一個隱含的邊框檢查從1.3版本(這可能對索引進行),但你正在檢查way一個ST_Transform,這意味着,經過該查詢必須掃描所有行。可以嘗試重寫在其原始SRID中保留way的查詢嗎?喜歡ST_Distance(way,ST_Transform(...,<srid of way>))

+0

我需要的其實是對象的半徑內(存儲在/緯度)米,這就是爲什麼我要改變mercator的一切。任何其他方法呢? – Mulone 2011-02-03 10:52:11