代码之家  ›  专栏  ›  技术社区  ›  skyman

获取框中包含的最左右上下点

  •  0
  • skyman  · 技术社区  · 14 年前

    我将兴趣点(poi)存储在postgresql数据库中,并通过php脚本将其检索到android应用程序。为了减少互联网使用,我想让我的移动应用程序知道当前显示区域附近是否有任何点。

    我的想法是存储包含已检索到的所有点的矩形的边界(换句话说:已检索到的最西边左侧(西边)的最近点、已检索到的最北边上方(北边)的最近点等),当屏幕的任何边超出这个界限。

    当前,我可以使用以下方法检索“单屏幕”(在当前显示的地图覆盖的区域)中的点:

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

    现在我需要知道每个方向上最远的四个点,这样我就可以检索下四个“更远”的点。

    有没有可能直接从postgresql获取这些点(或框)(可能使用一些“聚合点到框”函数)?

    1 回复  |  直到 14 年前
        1
  •  0
  •   Community rcollyer    7 年前

    您可以使用距离运算符( <-> )结合 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可以对列(如果有)使用索引,而不需要扫描表。由于距离是一个计算值,因此始终需要表扫描,查询的性能也将类似。一 query analysis 可能会有其他的原因让你更喜欢一个陈述,所以你应该在选择一种方法之前这样做。