2010-08-22 53 views
4

我已经能够创建php函数来确定给定邮政编码的一定范围内的邮政编码列表。但是,我的下一个任务更复杂一点。用于确定邮编接近度/范围的MySQL函数

比方说表有以下栏目:

id, 
username 
info 
latitude 
longitude 
range 

的每条记录都有一个唯一的行ID,一些信息,纬度,经度,并从这些坐标的人希望这个条目的最大范围被发现。因此,如果我使用坐标-20和50创建一个条目范围为15的条目,这意味着我只希望距坐标-20和50的15英里内的人能够看到我的条目。计算用户运行搜索的经度和纬度是一件小事。

当用户搜索数据库时,应检索纬度和经度坐标的所有记录,其范围是lat/long用户范围内的值。

所以,这将是

$userLat的使用距离公式来说明代码的非功能性示例=在运行搜索

$userLong的用户的纬度=用户的经度那正在运行搜索

SELECT info FROM table 
WHERE sqrt(($userLat - lat)^2 - ($userLong - long)^2) <= range 
ORDER BY username ASC 

这将是理想的,但从编码的角度来看它是无效的。有没有办法在一个查询中使用PHP和MySQL来运行上述比较?这将涉及能够使用给定行中的多个列值运行操作。


UPDATE +溶液

我创造了另一个问题条目,解决了这个问题,有一个非常紧凑的函数来完成这个问题想要什么。 coderpros给出的功能是它的灵感(他的功能在某些情况下有更好的处理能力)。但是,由于我使用我的功能对输入进行了很大程度的控制,因此我创建了一个单独的函数。它可以在下面的链接中找到:

MySQL User Defined Function for Latitude Longitude Syntax

回答

6

,我写一定要为你做的伎俩这个漂亮可爱的小MySQL的功能。

BEGIN 
    DECLARE x decimal(18,15); 
    DECLARE EarthRadius decimal(7,3); 
    DECLARE distInSelectedUnit decimal(18, 10); 

    IF originLatitude = relativeLatitude AND originLongitude = relativeLongitude THEN 
      RETURN 0; -- same lat/lon points, 0 distance 
    END IF; 

    -- default unit of measurement will be miles 
    IF measure != 'Miles' AND measure != 'Kilometers' THEN 
      SET measure = 'Miles'; 
    END IF; 

    -- lat and lon values must be within -180 and 180. 
    IF originLatitude < -180 OR relativeLatitude < -180 OR originLongitude < -180 OR relativeLongitude < -180 THEN 
      RETURN 0; 
    END IF; 

    IF originLatitude > 180 OR relativeLatitude > 180 OR originLongitude > 180 OR relativeLongitude > 180 THEN 
     RETURN 0; 
    END IF; 

    SET x = 0.0; 

    -- convert from degrees to radians 
    SET originLatitude = originLatitude * PI()/180.0, 
     originLongitude = originLongitude * PI()/180.0, 
     relativeLatitude = relativeLatitude * PI()/180.0, 
     relativeLongitude = relativeLongitude * PI()/180.0; 

    -- distance formula, accurate to within 30 feet 
    SET x = Sin(originLatitude) * Sin(relativeLatitude) + Cos(originLatitude) * Cos(relativeLatitude) * Cos(relativeLongitude - originLongitude); 

    IF 1 = x THEN 
      SET distInSelectedUnit = 0; -- same lat/long points 
      -- not enough precision in MySQL to detect this earlier in the function 
    END IF; 

    SET EarthRadius = 3963.189; 
    SET distInSelectedUnit = EarthRadius * (-1 * Atan(x/Sqrt(1 - x * x)) + PI()/2); 

    -- convert the result to kilometers if desired 
    IF measure = 'Kilometers' THEN 
      SET distInSelectedUnit = MilesToKilometers(distInSelectedUnit); 
    END IF; 

    RETURN distInSelectedUnit; 
END 

它将originLatitude,originLongitude,relativeLatitude,relativeLongitude和measure作为参数。度量可以简单地为MilesKilometers

希望帮助!

+0

非常感谢您的快速和翔实的答复。请原谅我的白痴,但我不熟悉使用自定义mysql函数。我究竟如何使用这个与PHP? – user396404 2010-08-23 00:24:01

+0

那么,你需要做的是在你的mySQL数据库中创建上述功能,然后你可以在你的php中调用它,如下所示: $ sql =“SELECT * FROM users WHERE CalculateDistance(userLat,userLong,relLat,relLong, 'miles)<15; 这有道理吗? – coderpros 2010-08-23 00:41:02

+0

啊,呃。只是最后一件事,我应该准备好使用它。 在下面的部分: CalculateDistance(userLat,userLong,relLat,relLong,'英里)<15 我会被传递userLat和userLong的值作为PHP变量和relLat和relLong将是列的名称在MySQL的。另外,15将被该行的范围列的值替换。你的代码会这样做吗?对不起,只是想确定一下,因为设置一些东西并花费数小时来贬低错误的东西是一场噩梦。我相信你明白。 – user396404 2010-08-23 01:44:48