2010-07-16 5 views
1

J'ai une base de données SQL où je stocke la longitude et la latitude d'une application d'iPhone. J'ai besoin d'interroger tous les enregistrements à partir d'un emplacement donné à l'autre endroit le plus loin. Par exemple, j'ai la longitude x et la latitude y.Trouver et ordonner la latitude et la longitude en SQL

Je veux d'abord que tous les records dont la longitude correspond le plus étroitement à x et dont la latitude correspond le plus étroitement. J'ai besoin de tous les enregistrements un par un dans la chaîne du plus proche au plus éloigné. Plus l'emplacement est éloigné, plus la valeur de la longitude et de la latitude sera grande que x et y.

J'espère que vous avez compris et j'attends la réponse.

Répondre

0

En supposant que vous avez interrogé l'emplacement de départ latitude/longitude et ID d'emplacement ... J'utilise LAT $, $ LON et ID $ comme des espaces réservés:

select locID, locName, locDesc, lat, lon, locDiff 
from (
    select locID, locName, locDesc, lat, lon, ABS(lat - $LAT) + ABS(lon - $LON) as locDiff 
     from locationTable 
    where locID <> $ID 
) a 
order by locDiff 

Espérons que cela aide ... peut-être pas la méthode la plus optimisée, mais elle devrait être assez proche.

+0

désolé mais pouvez-vous expliquer cette requête? – Neutralizer

+0

Quelle partie de vous confondre? La sous-requête interne extrait tous les emplacements sauf celui sur lequel vous comparez et soustrait les valeurs de latitude et de longitude de celle que vous comparez. Il utilise la fonction ABS pour obtenir la valeur absolue (non négative) des résultats. La requête externe extrait simplement les données de la requête interne ordonnée par la distance. Après l'avoir vu, je recommanderais Mark Bannisters qui utilise un théorème plus précis. – Fosco

1

similaires à Fosco, mais en utilisant le théorème de Pythagore:

select locID, locName, locDesc, lat, lon, locDiff from 
(select locID, locName, locDesc, lat, lon, 
sqrt((lat - $LAT)*(lat - $LAT) + (lon - $LON)*(lon - $LON)) as locDiff 
from locationTable 
where locID <> $ID) a 
order by locDiff 

Pour des distances très grandes (ou des endroits éloignés de l'équateur), vous devriez idéalement utiliser une géodésique.

2

La distance avec la latitude et la longitude n'est pas un calcul simple, mais une trigonométrie sphérique.

acos(cos(lat1)*cos(lon1)*cos(lat2)*cos(lon2) + 
    cos(lat1)*sin(lon1)*cos(lat2)*sin(lon2) + 
    sin(lat1)*sin(lat2)) * R(adius of the earth) 

donc cette requête

select locID, locName, locDesc, lat, lon, locDiffMeters 
from (select locID, locName, locDesc, lat, lon, 
      acos(cos($lat)*cos($lon)*cos(lat)*cos(lon) + 
        cos($lat)*sin($lon)*cos(lat)*sin(lon) + 
        sin($lat)*sin(lat)) * 6,371,000 -- earths radius in meters 
       as locDiffMeters 
     from locationTable  
    where locID <> $ID  
) a  
order by locDiffMeters  

est probablement la bonne réponse, supposant que vous avez que capable d'une bibliothèque de mathématiques.

+0

votre réponse a l'air cool. Je ne suis pas très bon en maths mais j'essaie de comprendre votre requête. Pouvez-vous me dire pourquoi avez-vous pris d'autres champs que Lon/Lat dans votre requête? – Neutralizer

+0

J'ai utilisé la requête de base de Fosco ci-dessus/ci-dessous, en changeant juste le calcul distinct pour utiliser la distance réelle sur une sphère.Vous avez besoin d'un point de départ (indiqué par $ ID, $ LAT et $ LON) et nous supposons que votre table de points a locID, locName, locDesc, lat et lon. Vous n'avez pas fourni de définition de table. nous en aurions utilisé un s'il avait été fourni (indice, indice). –

0

Si vous n'avez pas à faire de grandes distances (voir la réponse d'Adam), vous pouvez utiliser le geometric types de PostgreSQL et le functions associé.

0

Si vous utilisez Postgresql, ajoutez l'extension PostGIS et consultez la ST_Distance_Sphere

ST_Distance_Sphere - Retourne la distance minimum en mètres entre deux géométries de latitude/longitude LON. Utilise une terre sphérique et un rayon de 6370986 mètres. Plus rapide que ST_Distance_Spheroid, mais moins précis. Les versions de PostGIS antérieures à la version 1.5 ne sont implémentées que pour les points.

SELECT round(CAST(ST_Distance_Sphere(ST_Centroid(the_geom), ST_GeomFromText('POINT(-118 38)',4326)) As numeric),2) As dist_meter ... 
Questions connexes