GVKun编程网logo

MySQL 大圆距离(Haversine 公式)(mysql大小)

11

在这里,我们将给大家分享关于MySQL大圆距离的知识,让您更了解Haversine公式的本质,同时也会涉及到如何更有效地Haversine公式与PHP、Haversine公式使用SQLServer查找

在这里,我们将给大家分享关于MySQL 大圆距离的知识,让您更了解Haversine 公式的本质,同时也会涉及到如何更有效地Haversine公式与PHP、Haversine公式使用SQL Server查找最接近的场所-vb.net、ImportError: this is MySQLdb version (1, 2, 5, ''final'', 1), but _mysql is version (1, 4, ...、MySQL Crash Course #16# Chapter 24. Using Cursors + mysql 循环的内容。

本文目录一览:

MySQL 大圆距离(Haversine 公式)(mysql大小)

MySQL 大圆距离(Haversine 公式)(mysql大小)

我有一个有效的 PHP 脚本,它获取经度和纬度值,然后将它们输入到 MySQL 查询中。我想只做MySQL。这是我当前的 PHP 代码:

if ($distance != "Any" && $customer_zip != "") { //get the great circle distance    //get the origin zip code info    $zip_sql = "SELECT * FROM zip_code WHERE zip_code = ''$customer_zip''";    $result = mysql_query($zip_sql);    $row = mysql_fetch_array($result);    $origin_lat = $row[''lat''];    $origin_lon = $row[''lon''];    //get the range    $lat_range = $distance/69.172;    $lon_range = abs($distance/(cos($details[0]) * 69.172));    $min_lat = number_format($origin_lat - $lat_range, "4", ".", "");    $max_lat = number_format($origin_lat + $lat_range, "4", ".", "");    $min_lon = number_format($origin_lon - $lon_range, "4", ".", "");    $max_lon = number_format($origin_lon + $lon_range, "4", ".", "");    $sql .= "lat BETWEEN ''$min_lat'' AND ''$max_lat'' AND lon BETWEEN ''$min_lon'' AND ''$max_lon'' AND ";    }

有谁知道如何使这个完全 MySQL ?我浏览了一些互联网,但大多数关于它的文献都很混乱。

答案1

小编典典

来自Google Code FAQ - Creating a Store Locator with PHP, MySQL & Google
Maps:

下面的 SQL 语句将查找距离 37, -122 坐标 25 英里半径范围内最近的 20
个位置。它根据该行的纬度/经度和目标纬度/经度计算距离,然后仅询问距离值小于 25 的行,按距离对整个查询进行排序,并将其限制为 20
个结果。要按公里而不是英里搜索,请将 3959 替换为 6371。

SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin(radians(lat)) ) ) AS distance FROM markers HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;

Haversine公式与PHP

Haversine公式与PHP

如何解决Haversine公式与PHP?

您使用的公式似乎是反 余弦 而不是 haversine 公式。haversine公式确实更适合计算球体上的距离,因为它不容易出现舍入误差。

/**
 * Calculates the great-circle distance between two points, with
 * the haversine formula.
 * @param float $latitudeFrom Latitude of start point in [deg decimal]
 * @param float $longitudeFrom Longitude of start point in [deg decimal]
 * @param float $latitudeto Latitude of target point in [deg decimal]
 * @param float $longitudeto Longitude of target point in [deg decimal]
 * @param float $earthRadius Mean earth radius in [m]
 * @return float distance between points in [m] (same as earthRadius)
 */
function haversineGreatCircledistance(
  $latitudeFrom, $longitudeFrom, $latitudeto, $longitudeto, $earthRadius = 6371000)
{
  // convert from degrees to radians
  $latFrom = deg2rad($latitudeFrom);
  $lonFrom = deg2rad($longitudeFrom);
  $latTo = deg2rad($latitudeto);
  $lonTo = deg2rad($longitudeto);

  $latDelta = $latTo - $latFrom;
  $lonDelta = $lonTo - $lonFrom;

  $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
    cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
  return $angle * $earthRadius;
}

PS我找不到您的代码中的错误,所以这只是您写的错字$lat= 41.9133741000 $lat= 12.5203944000吗?也许您只是使用$ lat = 12.5203​​944000和$ long = 0进行了计算,因为您重写了$ lat变量。

编辑:

测试了代码,并返回了正确的结果:

$center_lat = 41.8350;
$center_lng = 12.470;
$lat = 41.9133741000;
$lng = 12.5203944000;

// test with your arccosine formula
$distance =( 6371 * acos((cos(deg2rad($center_lat)) ) * (cos(deg2rad($lat))) * (cos(deg2rad($lng) - deg2rad($center_lng)) )+ ((sin(deg2rad($center_lat))) * (sin(deg2rad($lat))))) );
print($distance); // prints 9.662174538188

// test with my haversine formula
$distance = haversineGreatCircledistance($center_lat, $center_lng, $lat, $lng, 6371);
print($distance); // prints 9.6621745381693

解决方法

我想将此公式与php一起使用。我有一个保存了纬度和经度值的数据库。

我想在输入中具有一定的经度和纬度值的情况下,找到从该点到数据库中每个点的所有距离(以km为单位)。为此,我在googlemaps api上使用了公式:

( 6371 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) )

当然在php中使用deg2rad该值,我用radians替换了。值37,-122是我的input值,而lat,lng是我在数据库中的值。

下面是我的代码。问题是出了点问题,但我不明白。距离的值当然是错误的。

//values of latitude and longitute in input (Rome - eur,IT)
$center_lat = "41.8350";
$center_lng =  "12.470";

//connection to database. it works
(..)

//to take each value in the database:
    $query = "SELECT * FROM Dati";
    $result = mysql_query($query);
    while ($row = @mysql_fetch_assoc($result)){
        $lat=$row[''Lat'']);
        $lng=$row[''Lng'']);
    $distance =( 6371 * acos((cos(deg2rad($center_lat)) ) * (cos(deg2rad($lat))) * (cos(deg2rad($lng) - deg2rad($center_lng)) )+ ((sin(deg2rad($center_lat))) * (sin(deg2rad($lat))))) );
    }

对于值,例如:$ lat = 41.9133741000 $ lng = 12.5203​​944000

我的输出为distance =“ 4826.9341106926”

Haversine公式使用SQL Server查找最接近的场所-vb.net

Haversine公式使用SQL Server查找最接近的场所-vb.net

我正在从表单中获取邮政编码。然后,我可以将这些邮政编码转换为lng,lat坐标,因为这些存储在表中。

SELECT lng, lat from postcodeLngLat WHERE postcode = ''CV1''

我还有另一张桌子,上面存放着一些场馆的家具。

SELECT v.lat, v.lng, v.name, p.lat, p.lng, p.postcode, ''HAVERSINE'' ASdistance FROM venuepostcodes v, postcodeLngLat p WHERE p.outcode = ''CB6'' ORDERBY distance

我要尝试做的是创建一个数据网格,该数据网格显示每个场所与邮政编码(在本例中为CV1)之间的距离。我知道Haversine公式应该可以达到我想要达到的目的,但是我不知道该从哪里开始将其合并到查询中。我认为公式需要转到我''HAVERSINE''在上面的查询中输入的位置。

有任何想法吗?

编辑

SELECT o.outcode AS lead_postcode, v.venue_name, 6371.0E * ( 2.0E *asin(casewhen 1.0E < (sqrt(square(sin(((RADIANS(CAST(o.lat ASFLOAT)))-(RADIANS(CAST(v.lat AS FLOAT))))/2.0E)) + (cos(RADIANS(CAST(v.lat ASFLOAT))) * cos(RADIANS(CAST(o.lat AS FLOAT))) *square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-(RADIANS(CAST(v.lng ASFLOAT))))/2.0E))))) then 1.0E else (sqrt(square(sin(((RADIANS(CAST(o.lat ASFLOAT)))-(RADIANS(CAST(v.lat AS FLOAT))))/2.0E)) + (cos(RADIANS(CAST(v.lat ASFLOAT))) * cos(RADIANS(CAST(o.lat AS FLOAT))) *square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-(RADIANS(CAST(v.lng ASFLOAT))))/2.0E))))) end )) AS distance FROM venuepostcodes v, outcodepostcodeso WHERE o.outcode = ''CB6'' ORDER BY distance

答案1

小编典典

我认为您最好将其放入UDF并在查询中使用它:

SELECT v.lat, v.lng, v.name, p.lat, p.lng, p.postcode, udf_Haversine(v.lat, v.lng, p.lat, p.lng) AS distance FROM venuepostcodes v, postcodeLngLat p WHERE p.outcode = ''CB6'' ORDER BY distancecreate function dbo.udf_Haversine(@lat1 float, @long1 float, @lat2 float, @long2 float) returns float begin        declare @dlon float, @dlat float, @rlat1 float, @rlat2 float, @rlong1 float, @rlong2 float, @a float, @c float, @R float, @d float, @DtoR float        select @DtoR = 0.017453293        select @R = 3937 --3976        select             @rlat1 = @lat1 * @DtoR,            @rlong1 = @long1 * @DtoR,            @rlat2 = @lat2 * @DtoR,            @rlong2 = @long2 * @DtoR        select             @dlon = @rlong1 - @rlong2,            @dlat = @rlat1 - @rlat2        select @a = power(sin(@dlat/2), 2) + cos(@rlat1) * cos(@rlat2) * power(sin(@dlon/2), 2)        select @c = 2 * atn2(sqrt(@a), sqrt(1-@a))        select @d = @R * @c        return @d     end

ImportError: this is MySQLdb version (1, 2, 5, ''final'', 1), but _mysql is version (1, 4, ...

ImportError: this is MySQLdb version (1, 2, 5, ''final'', 1), but _mysql is version (1, 4, ...

(flask-demo) ➜ flask-demo git:(master) ✗ pip install mysqlclient==1.2.5 DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won''t be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Looking in indexes: http://pypi.douban.com/simple ERROR: Could not find a version that satisfies the requirement mysqlclient==1.2.5 (from versions: 1.3.0, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7, 1.3.8, 1.3.9, 1.3.10, 1.3.11rc1, 1.3.11, 1.3.12, 1.3.13, 1.3.14, 1.4.0rc1, 1.4.0rc2, 1.4.0rc3, 1.4.0, 1.4.1, 1.4.2, 1.4.2.post1, 1.4.3, 1.4.4) ERROR: No matching distribution found for mysqlclient==1.2.5 (flask-demo) ➜ flask-demo git:(master) ✗ pip install MySQL-python DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won''t be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Looking in indexes: http://pypi.douban.com/simple Requirement already satisfied: MySQL-python in /Users/wang/.virtualenvs/flask-demo/lib/python2.7/site-packages (1.2.5) (flask-demo) ➜ flask-demo git:(master) ✗ pip install mysqlclient==1.3.0 DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won''t be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support Looking in indexes: http://pypi.douban.com/simple Collecting mysqlclient==1.3.0 Downloading http://pypi.doubanio.com/packages/6a/91/bdfe808fb5dc99a5f65833b370818161b77ef6d1e19b488e4c146ab615aa/mysqlclient-1.3.0.tar.gz (76kB) |████████████████████████████████| 81kB 1.9MB/s Building wheels for collected packages: mysqlclient Building wheel for mysqlclient (setup.py) ... done Created wheel for mysqlclient: filename=mysqlclient-1.3.0-cp27-cp27m-macosx_10_14_intel.whl size=44252 sha256=9227ae6803ea4590b6d18684e525b4b14958d2403aee820c6181ab1578cca342 Stored in directory: /Users/wang/Library/Caches/pip/wheels/03/17/c0/a1134f10bd894aec20af7d555f675e02a83552609d128e0756 Successfully built mysqlclient Installing collected packages: mysqlclient Found existing installation: mysqlclient 1.4.4 Uninstalling mysqlclient-1.4.4: Successfully uninstalled mysqlclient-1.4.4 Successfully installed mysqlclient-1.3.0

MySQL Crash Course #16# Chapter 24. Using Cursors + mysql 循环

MySQL Crash Course #16# Chapter 24. Using Cursors + mysql 循环

 mysql中游标的使用案例详解(学习笔记)这篇讲得相当直白好懂了。

索引:

  1. cursor 基础讲解
  2. mysql 循环
  3. 书上的整合代码

cursor 基础讲解

 cursor 有点类似于 JDBC 中的 ResultSet ,允许我们在执行 SELECT 之后,一行一行地 FETCH 数据。

它只能被用在存储过程中!如果把存储过程比作函数,cursor 只能在这个函数体中(存储过程的内部)定义、打开、关闭,一旦存储过程执行完毕,它将不再存在(可以把 cursor 理解为一个局部变量)。

定义一个 cursor ,这个时候并没有执行 SELECT 语句:

CREATE PROCEDURE processorders()
BEGIN
   DECLARE ordernumbers CURSOR
   FOR
   SELECT ordernum FROM orders;
END;

打开 cursor,SELECT 语句就是在这个时候被执行的,数据被缓存到 cursor 中,在这之后可以 FETCH 数据:

OPEN ordernumbers;

关闭 cursor ,释放 cursor 所占用的所有内存和资源, 当然,即便不手动关闭,在存储过程结束时(执行到 END) cursor 也会自动关闭:

CLOSE ordernumbers;

接下来就是 FETCH 数据了,每次 FETCH 一次都是下一行!可以结合上面几个知识点做个小实验,上面是实验用的表:

DROP PROCEDURE IF EXISTS hello;

DELIMITER //

CREATE PROCEDURE hello()
BEGIN
   -- 声明局部变量,用于临时存储 FETCH 结果
   DECLARE o INT;

   -- 声明游标
   DECLARE ordernumbers CURSOR
   FOR
   SELECT order_num FROM orders;

   -- 打开游标(执行SELECT,缓存数据)
   OPEN ordernumbers;

   -- 取出第一个订单号放到 o 里,并打印
   FETCH ordernumbers INTO o;
   SELECT o;
   
   -- 取出第二个订单号放到 o 里,并打印
   FETCH ordernumbers INTO o;
   SELECT o;
   
   -- 关闭游标(释放内存、资源)
   CLOSE ordernumbers;
   
   -- 重新打开游标(重新执行SELECT,缓存数据)
   OPEN ordernumbers;
   
   -- 取出第 ? 个订单号放到 o 里,并打印
   FETCH ordernumbers INTO o;
   SELECT o; -- 可以猜到,依然是第一个订单号

END // 

DELIMITER ;

CALL hello();

 

mysql 循环

 mySQL 本身的循环其实挺简单的,但是书上写的循环有点特殊。

基本循环示例:

while ↓

DROP PROCEDURE IF EXISTS hello;

DELIMITER //

CREATE PROCEDURE hello()
BEGIN
    DECLARE v1 INT DEFAULT 5;

    WHILE v1 > 0 DO
    SET v1 = v1 - 1;
    SELECT v1;
    END WHILE;
END // 

DELIMITER ;

CALL hello();

repeat ↓

DROP PROCEDURE IF EXISTS hello;

DELIMITER //

CREATE PROCEDURE hello()
BEGIN
    DECLARE v1 INT DEFAULT 5;

    REPEAT
    SET v1 = v1 - 1;
    SELECT v1;
    UNTIL v1 = 0 END REPEAT;
END // 

DELIMITER ;

CALL hello();

loop ↓

DROP PROCEDURE IF EXISTS hello;

DELIMITER //

CREATE PROCEDURE hello()
BEGIN
    DECLARE v1 INT DEFAULT 5;

    label1: LOOP
    
    SET v1 = v1 - 1;
    SELECT v1;
    IF v1 > 0 THEN
    ITERATE label1; -- 继续循环 相当于continue
    END IF;
    LEAVE label1; -- 相当于 break
    
    END LOOP;
END // 

DELIMITER ;

CALL hello();

PS. 为了确保可以直接 COPY 到命令行执行,上面的代码缩进有点问题。。。

书上的循环示例:

CREATE PROCEDURE processorders()
BEGIN

   -- Declare local variables
   DECLARE done BOOLEAN DEFAULT 0;
   DECLARE o INT;

   -- Declare the cursor
   DECLARE ordernumbers CURSOR
   FOR
   SELECT order_num FROM orders;

   -- Declare continue handler
   DECLARE CONTINUE HANDLER FOR SQLSTATE ''02000'' SET done=1;

   -- Open the cursor
   OPEN ordernumbers;

   -- Loop through all rows
   REPEAT

      -- Get order number
      FETCH ordernumbers INTO o;

   -- End of loop
   UNTIL done END REPEAT;

   -- Close the cursor
   CLOSE ordernumbers;

END;

 首先要看懂这句话

DECLARE CONTINUE HANDLER FOR SQLSTATE ''02000'' SET done=1;

意思就是出现 SQLSTATE ''02000'' 这句话时就执行 SET done=1

而 SQLSTATE ''02000'' 等价于 not found ,它是在 FETCH 不到数据的时候出现的,因此拿不到数据的时候 done 变为真就结束循环了。。。

 书上的整合代码

CREATE PROCEDURE processorders()
BEGIN

   -- Declare local variables
   DECLARE done BOOLEAN DEFAULT 0;
   DECLARE o INT;
   DECLARE t DECIMAL(8,2);

   -- Declare the cursor
   DECLARE ordernumbers CURSOR
   FOR
   SELECT order_num FROM orders;
   -- Declare continue handler
   DECLARE CONTINUE HANDLER FOR SQLSTATE ''02000'' SET done=1;

   -- Create a table to store the results
   CREATE TABLE IF NOT EXISTS ordertotals
      (order_num INT, total DECIMAL(8,2));

   -- Open the cursor
   OPEN ordernumbers;

   -- Loop through all rows
   REPEAT

      -- Get order number
      FETCH ordernumbers INTO o;

      -- Get the total for this order
      CALL ordertotal(o, 1, t);

      -- Insert order and total into ordertotals
      INSERT INTO ordertotals(order_num, total)
      VALUES(o, t);

   -- End of loop
   UNTIL done END REPEAT;

   -- Close the cursor
   CLOSE ordernumbers;

END;

 

这些活到底谁来做好呢 ? 是上层应用程序 还是 数据库 ? 。 。。 待更新。。

 

今天关于MySQL 大圆距离Haversine 公式的介绍到此结束,谢谢您的阅读,有关Haversine公式与PHP、Haversine公式使用SQL Server查找最接近的场所-vb.net、ImportError: this is MySQLdb version (1, 2, 5, ''final'', 1), but _mysql is version (1, 4, ...、MySQL Crash Course #16# Chapter 24. Using Cursors + mysql 循环等更多相关知识的信息可以在本站进行查询。

本文标签: