Le moyen le plus rapide de le faire est d'utiliser les extensions géospatiales pour MySQL, ce qui devrait être assez simple car vous utilisez déjà une table MyISAM. La documentation de ces extensions peut être trouvée ici :http:/ /dev.mysql.com/doc/refman/5.6/en/spatial-extensions.html
Ajoutez une nouvelle colonne avec un type de données POINT :
ALTER TABLE `adverts`
ADD COLUMN `geopoint` POINT NOT NULL AFTER `longitude`
ADD SPATIAL KEY `geopoint` (`geopoint`)
Vous pouvez ensuite remplir cette colonne à partir de vos champs de latitude et de longitude existants :
UPDATE `adverts`
SET `geopoint` = GeomFromText(CONCAT('POINT(',`latitude`,' ',`longitude`,')'));
L'étape suivante consiste à créer une zone de délimitation basée sur la latitude et la longitude d'entrée qui seront utilisées dans votre WHERE
clause sous forme de CONTAINS
contrainte. Vous devrez déterminer un ensemble de X,Y POINT
coordonnées qui répondent à vos besoins en fonction de la zone de recherche souhaitée et du point de départ donné.
Votre requête finale recherchera tous les POINT
les données qui se trouvent dans votre recherche POLYGON
, et vous pouvez ensuite utiliser un calcul de distance pour affiner et trier davantage vos données :
SELECT a.*,
ROUND( SQRT( ( ( (adverts.latitude - '53.410778') * (adverts.latitude - '53.410778') ) * 69.1 * 69.1 ) + ( (adverts.longitude - '-2.97784') * (adverts.longitude - '-2.97784') * 53 * 53 ) ), 1 ) AS distance
FROM adverts a
WHERE a.type_id = 3
AND CONTAINS(a.geopoint, GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'))
HAVING distance < 25
ORDER BY distance DESC
LIMIT 0, 30
Notez que le GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))')
dans ce qui précède ne fonctionnera pas , vous devrez remplacer les coordonnées par des points valides autour de votre début de recherche. Si vous vous attendez à ce que la lat/long change, vous devriez envisager d'utiliser un déclencheur pour conserver le POINT
données et SPATIAL KEY
associé à jour. Avec de grands ensembles de données, vous devriez voir des performances considérablement améliorées sur le calcul d'une distance pour chaque enregistrement et le filtrage à l'aide d'un HAVING
clause. J'ai personnellement défini des fonctions à utiliser pour déterminer la distance et créer le POLYGON
englobant .