2010-04-03 119 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

相关问题