2010-08-22 23 views
4

J'ai été capable de créer une fonction PHP pour déterminer une liste de codes postaux dans une certaine plage d'un code postal donné. Cependant, ma prochaine tâche est un peu plus complexe.Fonction MySQL pour déterminer la proximité du code postal

Disons que la table contient les colonnes suivantes:

id, 
username 
info 
latitude 
longitude 
range 

Chaque enregistrement a une id ligne unique, certaines informations, une latitude, une longitude et une portée maximale de ces coordonnées que la personne veut cette entrée être trouvé pour. Donc, si je crée une entrée avec les coordonnées -20, 50 avec une gamme de 15, cela signifie que je veux seulement que les gens dans les 15 miles des coordonnées -20, 50 pour pouvoir voir mon entrée. Déterminer la latitude et la longitude de l'utilisateur exécutant la recherche est une question triviale. Lorsqu'un utilisateur effectue une recherche dans la base de données, tous les enregistrements doivent être récupérés pour les coordonnées de latitude et de longitude comprises dans la plage de valeurs de l'utilisateur lat/long.

Ainsi, un exemple non fonctionnel de code en utilisant la formule de distance pour illustrer ce serait

$userLat = La latitude de l'utilisateur qui exécute la recherche

$userLong = La longitude de l'utilisateur exécute la recherche

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

Cela serait idéal, mais ce n'est pas valable du point de vue du codage. Est-il possible d'exécuter les comparaisons ci-dessus en utilisant PHP et MySQL dans une requête? Cela impliquerait de pouvoir exécuter des opérations en utilisant plusieurs valeurs de colonne d'une ligne donnée.


MISE A JOUR + SOLUTION

J'ai créé une autre entrée de question qui porte sur cette question et a une fonction très compacte pour faire ce que cette question voulait. La fonction donnée par coderpros lui a servi d'inspiration (sa fonction est bien meilleure dans certaines situations). Cependant, puisque j'utilise ma fonction avec un grand degré de contrôle sur l'entrée, j'ai créé une fonction séparée. Il peut être trouvé sur le lien ci-dessous:

MySQL User Defined Function for Latitude Longitude Syntax

Répondre

6

Cette fonction nifty lil mySQL que j'ai écrit devrait certainement faire l'affaire pour vous.

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 

Il faut originLatitude, originLongitude, relativeLatitude, relativeLongitude et mesure en tant que paramètres. Mesure peut simplement être Miles ou Kilometers

Espérons que ça aide!

+0

Merci beaucoup pour la réponse rapide et informative. Pardonnez mon idiotie, mais je ne suis pas familier avec l'utilisation de fonctions mysql personnalisées. Comment exactement pourrais-je utiliser ceci avec php? – user396404

+0

Eh bien, ce que vous devez faire est de créer la fonction ci-dessus dans votre base de données mySQL, alors vous pouvez l'appeler dans votre php comme suit: $ sql = "SELECT * FROM utilisateurs où CalculateDistance (userLat, userLong, relLat, relLong, 'miles) <15; Est-ce logique? – coderpros

+0

ah, gotcha.Juste une dernière chose et je devrais être prêt à l'utiliser. Dans la partie ci-dessous: CalculateDistance (userLat, userLong, relLat, relLong, 'miles) <15 Je passerai les valeurs de userLat et userLong que les noms seraient variables php et relLat et relLong des colonnes mysql. De plus, 15 serait remplacé par la valeur de la colonne de plage pour cette rangée. Est-ce que votre code le ferait? Désolé, je veux juste m'assurer que depuis que je mets quelque chose en place et que je passe des heures à faire la mauvaise chose, c'est un cauchemar. Je suis sûr que vous comprenez. – user396404