【问题标题】:Get all records from MySQL database that are within Google Maps .getBounds?从 MySQL 数据库中获取 Google Maps .getBounds 中的所有记录?
【发布时间】:2011-06-17 14:42:25
【问题描述】:

好的,我有一个大约 1800 行的数据库,每个都有一列 latlong,我正在尝试做什么,它查询 Google Maps V3 .getBounds 结果类似于 ((33.564398518424134, -79.38014701875002), (35.375726155241175, -76.08424858125002)) 什么我想做的是获取数据库中纬度和经度在这些范围内的每条记录。有什么建议吗?

我想我必须推断地图的其他 2 个角,因为 .getBounds 只包含 2 个点(我想是地图的 2 个角),我希望在 4 个点以内。如果我这样做了,我最终会得到一个类似的数组......如果我错了,请纠正我,但这应该是地图的 NW、NE、SW、SE 角,以 lat-lng 为单位。

33.564398518424134, -79.38014701875002
33.564398518424134, -76.08424858125002
35.375726155241175, -79.38014701875002
35.375726155241175, -76.08424858125002

好的,如果我有这些数据,我将如何构建查询来获取这些坐标内的行?表被称为tilistings - 列是latlng ...如果有更简单的方法,或者我只是对我的方法感到疯狂,请随时告诉我。

谢谢

【问题讨论】:

    标签: php mysql google-maps


    【解决方案1】:

    所有以前的答案只适用于世界的 1/4!

    W3t Tr3y 的答案很接近,但有一个错误(额外的“

    所有这些都只适用于美国,因为它位于北半球。 它们不适用于南半球,也不适用于东部国家(格林威治右侧)。

    这是一个简单的解决方案,没有功能或复杂的东西。

    字母是按照您从 map.getBounds() 获取的顺序排列的结果,即 swlat、swlng、nelat、nelng = a、b、c、d。

    SELECT * FROM tilistings WHERE
    (CASE WHEN a < c
            THEN lat BETWEEN a AND c
            ELSE lat BETWEEN c AND a
    END) 
    AND
    (CASE WHEN b < d
            THEN lng BETWEEN b AND d
            ELSE lng BETWEEN d AND b
    END) 
    

    或另一个使用 and/or 的解决方案(你可以测试它的速度,我不知道如何在 WorkBench 中多次运行它)

    SELECT * FROM tilistings WHERE
    (a < c AND lat BETWEEN a AND c) OR (c < a AND lat BETWEEN c AND a)
    AND 
    (b < d AND lng BETWEEN b AND d) OR (d < b AND lng BETWEEN d AND b)
    

    现在您可以绘制整个世界的地图了 :) 我希望有人可以将上述答案标记为不正确,因为它们让我们为数百万像我这样的学习者浪费了大量时间。我想知道他们实际上不工作时如何获得如此多的选票!

    PS:您的地图像素边缘与坐标的精确 15 位小数值匹配的机会比错过整个 3/4 世界的机会小无数倍!

    【讨论】:

    • 您好!我试过这个,当我们缩小时效果很好,但是当我们放大到精确位置时,结果不是很准确。我正在使用 PHP 和 MySQL ...您认为在 SQL 中计算大十进制数时需要采取哪些具体步骤
    • 应该是:swlat, swlng, nelat, nelng = a, b, c, d(试图编辑答案,但SO说至少必须更改6个字符)
    • 这应该是公认的答案。谢谢你。它是如此简单,但我却在上面拔了头发。
    • 如何处理国际日期变更线?
    【解决方案2】:

    如果来自 Google:( (a, b), (c, d) )

    SELECT * FROM tilistings WHERE lat &gt; a AND lat &lt; c AND lng &gt; b AND lng &lt; d

    【讨论】:

    • 嗯,我认为这会比这更困难,谢谢我想太多了
    • v3 api。 map.getBounds().getNorthEast(); map.getBounds().getSouthWest();获取适当的 LatLng 对象。
    • Mike L.:你没有把事情复杂化。这个简短的答案仅适用于美国,即您只处理正数。如果您必须考虑赤道以下的纬度或格林威治以外的经度,则计算会更加复杂。看我的回答。
    • Segio 的答案是值得一看的——继续滚动。当您开始与新西兰等地打交道时,此解决方案完全失效。
    • 同意塞尔吉奥。这个答案太简单了——它没有考虑到初学者越过日期。弗拉基米尔的回答现在对我来说最有希望。
    【解决方案3】:

    我没有使用过 Google 的 API,但我的理解是,如果您从 getBounds 调用返回 ((33.564398518424134, -79.38014701875002), (35.375726155241175, -76.08424858125002)),则 (33.564398518424134, -79.38014701875002) 是西南角, (35.375726155241175, -76.08424858125002) 是东北角我这么说是因为我认为它们会返回东北角和西南角,并且我假设这些点是纬度、经度。

    如果那是正确的,那么 Bensiu 的查询就会起作用。通常使用 BETWEEN 效率更高。

    SELECT * FROM tilistings WHERE lat BETWEEN a AND c AND lng between b AND  d
    

    【讨论】:

      【解决方案4】:

      我现在发表评论为时已晚,但也许它对某人有用。 sergio unswer 不太正确,如果我没记错的话,对整个世界的查询必须看起来有点不同:

      SELECT * FROM tilistings WHERE (sw_lat < ne_lat AND lat BETWEEN sw_lat AND ne_lat) OR (sw_lat > ne_lat AND (lat BETWEEN sw_lat AND 180 OR lat BETWEEN -180 AND ne_lat)) (sw_lon < ne_lon AND lon BETWEEN sw_lon AND ne_lon) OR (sw_lon > ne_lon AND (lon BETWEEN sw_lon AND 180 OR lon BETWEEN -180 AND ne_lon))

      【讨论】:

      • 与其他解决方案不同,这对我来说在世界范围内始终有效。谢谢!
      【解决方案5】:

      弗拉基米尔答案的稍微简化的版本非常适合我。

      取一个由南边(south)、西边(west)、北边(north)和东边(east)组成的盒子包围的区域。这些可以从提供西南角和东北角的 Google Map .getBounds 派生 - 您只需要这两个角,因为它们完全描述了方形边界框。

      在本例中,我们的数据库表称为位置,并包含一个纬度和经度列。

      SELECT * FROM locations WHERE
      (latitude BETWEEN south AND north) AND
      ((west < east AND longitude BETWEEN west AND east) OR
       (west > east AND (longitude BETWEEN west AND 180 OR longitude BETWEEN -180 AND east)))
      

      这是基于这样一个事实,即我们只需要考虑穿越 180/-180 经线作为一种特殊情况 - 即西经比东经更高的值。在任何情况下,如果我们不越过那条线,西经将永远小于东经。

      关于纬度,南边的值始终低于北纬,因为没有环绕两极的概念。例如,要覆盖北极上空的区域,我们只需将所有经度(即从 -180 到 180)和从南部边界到 +90 的纬度设置为。

      【讨论】:

      • ^^ 这是正确的答案。完美而快速地工作。谢谢@胖僧。
      【解决方案6】:

      这对我有用:

      $condition1 = $a < $c ? "lat > $a AND lat < $c" : "lat > $a OR lat < $c";
      $condition2 = $b < $d ? "lon > $b AND lon < $d" : "lon > $d OR lon < $b";
      $q = "SELECT * FROM tilistings WHERE ( $condition1 ) AND ( $condition2 )";
      

      【讨论】:

        【解决方案7】:

        我们可以使用以下查询在 Maps.getBounds 北东和西南纬度以及北东和西南经度之间找到结果。

        搜索查询应介于 northEast.latitude 和 southWest.latitude 之间 AND northEast.longitude AND southWest.longitude

        $nelat=$_GET['nelat']-0.5;
        $nelng=$_GET['nelng']-0.5;
        $swlat=$_GET['swlat']-0.5;
        $swlng=$_GET['swlng']-0.5;
        
        $sql ="SELECT * FROM tablename where (CASE WHEN ".$nelat." < ".$swlat."
            THEN s.latitude BETWEEN ".$nelat." AND ".$swlat."
            ELSE s.latitude BETWEEN ".$swlat." AND ".$nelat."
        END) 
        AND
        (CASE WHEN ".$nelng." < ".$swlng."
                THEN s.longitude BETWEEN ".$nelng." AND ".$swlng."
                ELSE s.longitude BETWEEN ".$swlng." AND ".$nelng."
        END)";
        

        【讨论】:

          【解决方案8】:

          看看 MySQL 5.7 中可用的新空间数据和函数,现在也适用于 InnoDB。

          使用上面的例子,一个有1个mio记录的表大约需要1s才能得到某个边界框内的位置。

          使用 ST_Within() 和 ST_MakeEnvelope() 以及正确的空间索引,我可以在 0.01 秒内得到结果。

          【讨论】:

            【解决方案9】:

            来自我的要点https://gist.github.com/jesuGMZ/0d7f38d80e2f67d0bc4b7fb620345344

            让 MySQL >5.7 的表包含名为 location 的列类型 POINT 和以下 Google 地图响应:

            "geometry": {
                "bounds": {
                    "northeast": {
                        "lat": 40.5638447,
                        "lng": -3.5249115
                    },
                    "southwest": {
                        "lat": 40.3120639,
                        "lng": -3.8341618
                    }
                },
                //....
            

            您可以执行 SQL 查询来检索包含在该边界中的所有位置,如下所示:

            SELECT * FROM my_table
            WHERE Contains(
              ST_MakeEnvelope(
                ST_GeomFromText('POINT(40.5638447 -3.5249115)'),
                ST_GeomFromText('POINT(40.3120639 -3.8341618)')
              ),
              location
            );
            

            考虑索引位置以提高查询的性能(如果适用)。此外,可以使用Within 代替Contains 更改参数的顺序。

            有用的链接:

            【讨论】:

              【解决方案10】:

              我不确定上述说法是否正确。首先,我相信角落是 nelat、nelng、swlat、swlng 不是上面所说的“swlat、swlng、nwlat、nwlng”。其次,我相信 nelat 总是会比窗户的 swlat 高(除非窗户覆盖了我不确定谷歌地图甚至可能的地理极点之一)。

              最后,如果窗口覆盖国际日期变更线(大约 +/-180lng),即 d

              【讨论】:

                猜你喜欢
                • 2010-09-22
                • 2022-08-05
                • 1970-01-01
                • 1970-01-01
                • 2015-08-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多