2014-09-22 62 views
0

我有兩個表項目地點。一個項目可以使用locations.project_id參考的許多位置。此外,位置功能列locations.latitudelocations.longitude從加入表獲得最小的地理距離

我現在正在尋找一種有效的方式來查詢所有項目及其到固定點的最小距離。比方說,表中有兩個項目,每個項目都有兩個位置,我想獲得兩個項目以及距離最接近固定點的一個位置的距離。

我創建了一個.geography功能方便:

CREATE FUNCTION geography(locations) RETURNS GEOGRAPHY AS $$ 
    SELECT ST_GeographyFromText(
    'SRID=4326;POINT(' || $1.latitude || ' ' || $1.longitude || ')' 
) 
$$ LANGUAGE SQL 

現在下面的示例使用 「蘇黎世(47.36865,8.539183)」 作爲固定點:

SELECT 
    ST_Distance(locations.geography, ST_GeographyFromText('SRID=4326;POINT(47.36865 8.539183)')) AS distance 
    FROM "projects" 
    INNER JOIN "locations" ON "locations"."project_id" = "projects"."id" 

的查詢工作,但是,它將距離返回到具有最早創建日期的位置,而不是最近的位置。任何想法如何解決這個問題?

UPDATE

我的問題是完全錯誤的。 CTE實現我的目標非常簡單,但這是另一回事。我對這些噪音表示歉意。

+0

我不完全按照你的問題。創建日期適合表和查詢的位置。你是說你有兩個相同的地點,但是對於創作日期,你只想要最新的? – 2014-09-22 14:28:55

+0

@JohnBarça如果一個項目有多個位置,INNER JOIN顯然只適用於數據庫中最先出現的那個(通常是最早的那個)並計算距離。如果我首先創建一個遠離固定點的位置,然後另一個位置靠近固定點,那麼上面的查詢將返回距離最遠的位置。無論插入什麼時候,我都需要最短的距離。 – svoop 2014-09-22 17:25:10

+0

按st_distance(...)排序desc? – 2014-09-22 17:29:44

回答

1

PostGIS使用軸順序:經度,緯度(認爲X,Y)。您的距離可能不是您所期望的,因爲您目前正在索馬里搜索,而不是瑞士。

此外,由於您不斷重新生成geography類型並且沒有空間索引,因此您的方法效率非常低。考慮數據移動到空間類型,並去除冗餘列,例如:

ALTER TABLE locations ADD COLUMN geog geography(Point,4326); 
UPDATE locations SET 
    geog=ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)::geography; 
CREATE INDEX locations_geog_idx ON locations USING gist (geog); 
ALTER TABLE locations DROP COLUMN latitude; 
ALTER TABLE locations DROP COLUMN longitude; 

你總是可以訪問和查看使用字符串ST_X爲經度,或ST_AsTextST_AsLatLonText(geog::geometry)數據等47°22'7.140" N 8°32'21.059" E。現在你的查詢:

SELECT 
    ST_Distance(locations.geog, 
       ST_SetSRID(ST_MakePoint(8.539183, 47.36865), 4326)::geography)')) 
    AS distance 
FROM "projects" 
INNER JOIN "locations" ON "locations"."project_id" = "projects"."id"; 
+0

對於長/長指令您是對的,但是當我將實際案例減少到這個例子時,發生了這種情況。還有一個索引。無論如何,我正在提高你的答案,感謝你的詳細和正確的答案 - 只是我的問題是錯誤的。 – svoop 2014-09-24 19:59:58