<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                目的是,根據經緯度,實現查其找附近的人或地點,LBS 場景。 做基于地理位置的應用后臺,沒有使用 mongodb,看了網上的很多答案,其實也就是幾份答案而已,天下文章一大抄。 這里綜合網上的,結合自身,總結出了幾種根據經緯度的排序算法,測試可用,性能也還可以。逐步遞進優化,不同階段,不同使用。 這里 x 為緯度,y 為經度。 PS:SQL 代碼不完整,僅供閱讀參考,理解意思就好。 # [](https://www.chengxiaobai.com/mysql/mysql-according-to-the-latitude-and-longitude-search-sort#%E4%B8%80%E3%80%81-MySQL-%E4%B8%8D%E4%BD%BF%E7%94%A8%E7%A9%BA%E9%97%B4%E5%87%BD%E6%95%B0%EF%BC%8C%E7%AE%80%E5%8D%95%E7%89%88 "一、 MySQL 不使用空間函數,簡單版")一、 MySQL 不使用空間函數,簡單版 1\. 粗算,根據場景得到一個 range,計算經緯度,得到的是一個矩形區域 (A),不精確,但是已經有范圍這個雛形了,最容易實現的方式之一。 ~~~sql where latitude>y-range and latitude<y+range and longitude>x-range and longitude <x+range order by abs(longitude -x)+abs(latitude -y) limit 10; ~~~ 2\. 使用 PHP 函數計算出距離,排序即可。 ~~~php /** * @param $lat1緯度 * @param $lng1經度 * @param $lat2緯度 * @param $lng2經度 * @return float|int * 計算距離(KM) */ function GetDistance($lat1, $lng1, $lat2, $lng2) { $EARTH_RADIUS = 6378.137; $radLat1 = rad($lat1); $radLat2 = rad($lat2); $a = $radLat1 - $radLat2; $b = rad($lng1) - rad($lng2); $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))); $s = $s * $EARTH_RADIUS; $s = round($s * 10000) / 10000; return $s; } /** * @param $d * @return float * 轉換弧度 */ function rad($d) { return $d * pi() / 180.0; } ~~~ 排序的話,自己靈活實現。很多語言都有封裝排序算法,效率也挺高的。 * * * # [](https://www.chengxiaobai.com/mysql/mysql-according-to-the-latitude-and-longitude-search-sort#%E4%BA%8C%E3%80%81-MySQL-%E4%B8%8D%E4%BD%BF%E7%94%A8%E7%A9%BA%E9%97%B4%E5%87%BD%E6%95%B0%EF%BC%8C%E4%BC%98%E5%8C%96%E7%89%88 "二、 MySQL 不使用空間函數,優化版")二、 MySQL 不使用空間函數,優化版 這里的優化是對(一)中 range 的優化。根據范圍半徑,計算出經緯度的變化范圍,得到一個比較準確的 range,這里的范圍 (B) 是圓形的 (因為 $radius 是倆點間的距離)。 但是篩選時候的范圍 (C) 是矩形,所以精確上來說, 圓 B 是矩形 C 的內切圓,不在圓 B 但是在矩形 C 中的點也會出現在我們的 SQL 結果中。但是已經比 (一) 要好很多了。 ~~~php $radius = 1;//半徑范圍,單位km $rangeLat = 180 / pi() * $radius / 6372.797;//緯度范圍 $rangeLng = $rangeLat / cos($x * pi() / 180.0); //經度范圍 $maxLat = $x + $range; //x1 $minLat = $x - $range; //x0 $maxLng = $y + $lngR; //y1 $minLng = $y - $lngR; //y0 ~~~ 我見過把這個計算帶入到 SQL 中的,一大串 SQL,這種計算本來就不是 SQL 該有的,不推薦這樣做。 * * * # [](https://www.chengxiaobai.com/mysql/mysql-according-to-the-latitude-and-longitude-search-sort#%E4%B8%89%E3%80%81-MySQL-%E4%BD%BF%E7%94%A8%E7%A9%BA%E9%97%B4%E5%87%BD%E6%95%B0 "三、 MySQL 使用空間函數")三、 MySQL 使用空間函數 在(二)中,我們得到了 4 個點。這個就是矩形范圍,我們只要判斷是否在這個矩形內就好了。其實用到 MySQL 的空間函數可以支持任意多邊形。 還支持索引優化,MyISAM~才~能建立空間索引, MySQL 5.7 版本 InnoDB 也支持空間索引了。 > 優化程序將調查可用的空間索引是否能包含在使用某些函數的查詢搜索中,如 WHERE 子句中的 MBRContains () 或 MBRWithin () 函數。 > --19.6.2. 使用空間索引 **這里的核心思想就是用一個范圍判斷某個點是否在這個范圍內。** 在數據庫有一個類型為 geometry 的列 g。 ~~~sql select id,AsText(g) from geom where MBRContains(GeomFromText('Polygon((x0 y0,x1 y0,x1 y1,x0 y1,x0 x0))'),g); ~~~ 即可準確篩選出在這個范圍內的點。即使后面跟 ORDER BY 限制距離性能也沒有太大影響。 ~~~sql SELECT id, AsText(g), SQRT(POW( ABS( X(g) - X(x)), 2) + POW( ABS(Y(g) - Y(y)), 2 )) AS distance FROM geom[*1] WHERE MBRIntersects(g, GeomFromText('Polygon((x0 y0,x1 y0,x1 y1,x0 y1,x0 x0))'))[*2] AND SQRT(POW( ABS( X(g) - X(x)), 2) + POW( ABS(Y(g) - Y(y)), 2 )) < radius[*3] ORDER BY distance;[*4] ~~~ *1: 從 geom 表中根據倆點間的距離公式計算結果,命名為 distance 2: 條件 1,g 列中的點和算出來的范圍相交!相交!相交!注意我用的是 MBRIntersects (),不是 MBRContains () 3: 條件 2,distance 小于給定的半徑 radius 4: 根據 distance 排序* **上面是根據官方文檔寫的示例代碼,比較重要,如果你沒看懂,沒關系,我來舉個栗子** 這里選用 MBRContains () 來舉例子,你可以自己實驗下 MBRWithin () 函數,注意參數順序就好了,我這里得到的結果是一樣的。 函數用法:MBRContains (*g1*,*g2*) 函數說明:返回 1 或 0 以指明*g1*的最小邊界矩形是否包含*g2*的最小邊界矩形 函數已經說明了是 g1 是否包含 g2,所以不要弄反了;這里的矩形支持任意多變形 目標點:D (1,1) 也可以是范圍喲,見注釋 \* 1 范圍:E (0 0,0 3,3 3,3 0,0 0),閉合矩形,其實支持任意閉合多邊形 ~~~sql SELECT id,name from geom where MBRContains(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'), GeomFromText('Point(1 1)'));[*1] ~~~ *1: 這里的目標點 D 也支持任意多邊形,參數不再是 Point () 而是 Polygon ()* **這條 SQL 可以解釋為判斷點 D 是否在范圍內 E。** ~~~sql SELECT id,name,AsText(g)[*1] from geom where MBRContains(GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'), g); ~~~ *1: 因為 g 列是 geometry 類型的,所以要用 AsText 轉換下再展現出來* **這條 SQL 可以解釋為列出數據庫中所有包含在范圍 E 中的點。** 更多相交、包含、接觸等方法見上面開發文檔 《19.5.5. 關于幾何最小邊界矩形(MBR)的關系》 * * * ### [](https://www.chengxiaobai.com/mysql/mysql-according-to-the-latitude-and-longitude-search-sort#%E5%9B%9B%E3%80%81geohash "四、geohash")四、geohash 這個 GeoHash 是將二維的經緯度轉換成字符串,字符串長度越長,精度就越精細。倆個字符串長度匹配的位數越多,就越接近,絕大部分情況看起來是這個樣子的,但有例外。 類似于:(G->)|J…… 我 | K……|(<-H) 因為 GeoHash 是將區域劃分為一個個規則矩形,所以在同一個矩形中,GeoHash 是一樣的,但是會出現一個邊際問題:G、H 倆個左右相鄰的矩形,我在 G 的右邊際處 (右邊際和 H 相鄰),餐廳 J 在 G 的左邊際,餐廳 K 也在 H 的左邊際,通過 GeoHash 得出來的結果是餐廳 J 離我更近,顯然不合理。 可以通過加大矩形區域的精細程度和擴大相似范圍解決。 根據匹配相應的位數,在 MySQL 加入索引,可以極大提高效率。GeoHash 和經緯度的轉換,網上都有現成的代碼,這里不再展示,PHP 還有對應的 C 拓展能提高計算速度。 > \* 在緯度相等的情況下: > > \* 經度每隔 0.00001 度,距離相差約 1 米; > > \* 每隔 0.0001 度,距離相差約 10 米; > > \* 每隔 0.001 度,距離相差約 100 米; > > \* 每隔 0.01 度,距離相差約 1000 米; > > \* 每隔 0.1 度,距離相差約 10000 米。 > > \* 在經度相等的情況下: > > \* 緯度每隔 0.00001 度,距離相差約 1.1 米; > > \* 每隔 0.0001 度,距離相差約 11 米; > > \* 每隔 0.001 度,距離相差約 111 米; > > \* 每隔 0.01 度,距離相差約 1113 米; > > \* 每隔 0.1 度,距離相差約 11132 米。 > > Geohash,如果 geohash 的位數是 6 位數的時候,大概為附近 1 千米。 * * * ### [](https://www.chengxiaobai.com/mysql/mysql-according-to-the-latitude-and-longitude-search-sort#%E4%BA%94%E3%80%81Redis-GeoHash "五、Redis GeoHash")五、Redis GeoHash [官網在這里](https://matt.sh/redis-geo) Redis 也能玩定位? sure!并且效率奇高! 雖然也是通過 GeoHash (高性能、高精度版) 來實現的,但是它封裝了很多有用的方法,直接使用經緯度即可操作,能直接根據距離返回對應的點,支持直接返回 json,還支持排序輸出。 畢竟是 Redis,持久化和容量都是要考慮的問題。 但是 Redis 從來不是孤軍奮戰的工具。 可以和 MySql 搭配,放在數據庫前扛著,里面存儲高頻定位點, MySQL 也支持定位 (方案三),合理使用應該很好的 MySQL 定位解決方案了。 以上就是根據現有資料整理的 MySQL 經緯度經緯解決方案,如果有更好的方案,歡迎評論區討論。 Happy Coding~ [http://howto-use-mysql-spatial-ext.blogspot.com](https://howto-use-mysql-spatial-ext.blogspot.com/) [http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html#a](https://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html#a)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看