2010-04-03 163 views
0

我在PostgreSQL數據庫中存儲興趣點(POI),並通過PHP腳本將它們檢索到Android應用程序。爲了減少互聯網使用量,我希望我的移動應用程序知道當前顯示區域附近是否有任何點。獲取包含在框中的大部分左側|右側|頂部|底部點

我的想法是存儲包含已經檢索到的所有點的矩形邊界(換言之:已經檢索到的最西部的最左邊的西部的最近點,已經檢索到的最北部的最近的北部的點) ),當屏幕的任何邊緣超出這個邊界時,我會進行下一個查詢。

目前我可以檢索這是在「單屏」點(以當前顯示的地圖覆蓋的區域)使用:

SELECT * FROM ch WHERE loc <@ (box '((".-$latSpan.", ".$lonSpan."),(".$latSpan.", ".-$lonSpan."))' + point '".$loc."') 

現在我需要在每個方向上知道四個最偏遠點,比我將能夠檢索到下四個「更遠程」點。

是否有可能直接從PostgreSQL獲得這些點(或框)(也許使用一些「聚合點到框」功能)?

+0

您確定框中的值的順序嗎?它看起來像在X(水平)座標中存儲緯度極值(N/S),在Y(垂直)中存儲經度。我希望這個盒子是'box((--longSpan,latSpan),(longSpan,-latSpan))'。 – outis 2010-04-03 00:45:11

回答

0

可以使用距離運營商(<->)與MIN聚合函數相結合,找到最近的距離,這樣可以減少問題尋找其他支柱與一些minimal quantity行。可以使用嚴格左側/右側/上方/下方運算符(<<,>>,|>>,<<|)將點限制在框的一側。由於兩個不同的點可能具有相同的距離,我們將limit結果分配給1行。假設屏幕方向,其中座標增加向下和向右(而不是地圖的方向,這增加了華北和華東地區),我們得到:

-- Above, or North 
SELECT * FROM ch WHERE loc <<| screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc <<| screen 
) LIMIT 1 

-- Right, or East 
SELECT * FROM ch WHERE loc >> screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc >> screen 
) LIMIT 1 

-- Below, or South 
SELECT * FROM ch WHERE loc |>> screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc |>> screen 
) LIMIT 1 

-- Left, or West 
SELECT * FROM ch WHERE loc << screen AND (loc <-> screen) = (
    SELECT MIN(loc <-> screen) AS mindist FROM ch 
    WHERE loc << screen 
) LIMIT 1 

注意,在水平方向上的最近點也可能是最接近點在垂直方向上;也就是說,上述四條語句的聯合可能少於四行。

我們可以得到四個最近點:

SELECT *, (loc <-> screen) AS distance FROM ch 
    WHERE NOT loc <@ screen 
    ORDER BY distance 
    LIMIT 4 

但是請注意,一些最近點的可能是同一方向對方。

我們可以

SELECT *, (loc <-> screen) AS distance FROM ch 
    WHERE distance = (
     SELECT MIN(loc <-> screen) AS mindist FROM ch 
) 
    LIMIT 1 

SELECT *, (loc <-> screen) AS distance FROM ch 
    WHERE NOT loc <@ screen 
    ORDER BY distance 
    LIMIT 1 

當計算列的最小(或最大),第一個將是可取的總體得到的最近點,因爲DBMS可以使用該列上的索引(如果有)並且不需要掃描該表。由於距離是一個計算值,因此始終需要進行表掃描,並且查詢的性能相似。 A query analysis可能出於某種原因偏好一個陳述,所以你應該在選擇方法之前這麼做。

+0

我需要一些時間來「編譯」你的答案...... 但是,是否有任何優勢'SELECT * FROM ch WHERE loc << |屏幕AND(loc <-> screen)=(SELECT MIN(loc <-> screen)AS mindist FROM ch WHERE loc << | screen)LIMIT 1' over'SELECT * FROM ch WHERE loc << | screen and ORDER BY(loc <-> screen)ASC LIMIT 1'? – skyman 2010-04-03 13:39:45

+0

@skyman:讀過我最後的評論。我懷疑你提到的兩個中的後者會表現更好,但運行查詢分析是可以肯定的。 – outis 2010-04-03 23:07:00

相關問題