2011-05-31 6 views
0

J'ai actuellement une requête de base de données qui calcule la distance entre chaque magasin dans la base de données à partir d'un emplacement "maison". Je calcule la distance de vol en utilisant cette formule.Latitude/Longitude Question mathématique (Distance entre deux coordonnées)

http://www.movable-type.co.uk/scripts/latlong.html

Je suis les commander et de les afficher. J'ai découvert une bien meilleure façon de le faire est seulement la recherche de magasins dont la latitude/longitude sont dans une fourchette. Par exemple, au lieu de calculer la distance entre chaque magasin dans la base de données (plus de 30000), ne groupez que ceux avec lat/long dans une certaine plage et calculez la distance entre ceux-ci.

En ce moment j'essaie de trouver comment calculer les limites réelles. La distance doit être inférieure à 5 km. Donc je divise 5 par 100 et plafonne la latitude et la longitude par ces montants.

SELECT storeid, storedescription, address, city, storebannerdescription, lat, lon, 
     ROUND (gc_dist (lat, lon, 43.758152, -79.746639), 1) AS distance 
     FROM storelatlon 
     WHERE ((lat-43.758152) < 0.05 AND (lat -43.758152) > -0.05) AND ((lon-(-79.746639)) < 0.05 AND (lon-(-79.746639)) > -0.05) 
     ORDER BY Distance 
+6

Quelle est votre question? –

+3

Je ne suis pas sûr de ce que vous demandez, mais je noterai que la soustraction des mesures angulaires ne vous dit rien sur les distances. –

+0

Quelle est la question? Je suppose que c'est "Est-ce une mise en œuvre valide ou bonne?" Aussi, quelle base de données utilisez-vous? Certaines bases de données prennent en charge les calculs lat/long (comme Oracle Locator), mais ce n'est pas forcément gratuit (Oracle Spatial ne l'est pas et il peut être difficile de dire où les lignes se terminent avec Locator et commencent par Spatial). D'autres bases de données fournissent également un support de base, y compris MySQL. – pickypg

Répondre

1

Cette méthode pourrait fonctionner, mais selon la façon dont largement distribués vos magasins sont, vous pouvez affiner vos besoin d'un peu de limites parce que vous allez dans latitute, vous traversez plus la longitude sur une distance donnée. Vous pouvez obtenir trop ou trop peu de points en filtrant de 0,05 degrés pour toutes les latitudes.

0

Je suppose que vous utilisez PostgreSQL en fonction de votre utilisation de gc_dist. Tant que PostGIS est installé, vous pouvez exécuter la logique souhaitée à l'aide de la fonctionnalité intégrée.

Vous devrez préparer votre table pour ceci:

En premier lieu, stocker votre position comme point de PostGIS. Je suggère d'utiliser WGS-84 pour les calculs géographiques.

Une fois que vous faites cela, vous pouvez interroger pour tous les points dans une certaine distance de votre position désirée à l'aide ST_Contains et ST_Buffer, où ST_Buffer enveloppe le point central que vous voulez trouver les voisins pour (-79,746639, 43,758152) à longue/ordre de lat.

Je n'ai jamais utilisé PostgreSQL pour cela, mais je l'ai fait avec Oracle. Il semble prendre la même configuration pour PostgreSQL que pour Oracle:

A. Dites à la base de données que vous allez créer une colonne basée sur la géométrie. Found syntax here. Ci-dessus, 4326 est un "SRID" constant désignant WGS-84.

B. Ajouter un index à la colonne. Found syntax here (cette page semble très utile).

CREATE INDEX desired_index_name 
ON table_name 
USING gist(desired_column_name); 

C. Ajoutez vos données.

INSERT INTO table_name (desired_column_name) 
VALUES('SRID=4326;POINT(-79.746639 43.758152)'); 

(je suis curieux de savoir si la chaîne ci-dessus doit être contenue par ST_GeomFromText en fonction d'autres exemples)

ou (I found here)

INSERT INTO table_name (desired_column_name) 
VALUES (ST_Transform(ST_MakePoint(-79.746639, 43.758152), 4326)); 

Note: Je suppose que c'est (X, Y), ce qui signifie la longitude et la latitude.

D. Interrogez vos données.

SELECT * FROM table_name 
WHERE 
    ST_Contains(
     ST_Buffer(
      ST_Transform(ST_MakePoint(-79.746639, 43.758152), 4326), 
      distance_probably_in_meters), 
     desired_column_name);