Question

Note: Bien que j'utilise une base de données de code postal avec zipcodes néerlandais, cette question est un pays indépendant

.

J'ai une base de données avec tous les Pays-Bas code postal + ses coordonnées x et y (latitude / longitude).

Je par exemple code postal: $baseZipCode = 1044; avec les coordonnées suivantes:

x coordinate = 4,808855
y coordinate = 52,406332

Maintenant, je veux trouver tous les autres codes postaux avec $range de $baseZipCode.

Par exemple:

SELECT
  zipcode
FROM
  zipcodes
WHERE
  ????? // Need help here

Le problème est que la terre est pas tout à fait rond. Je trouve beaucoup de tutoriels avec des calculs de from a to b mais ce n'est pas ce que je dois.

Est-ce que quelqu'un a une idée?


UPDATE Merci à Captaintokyo je trouve ceci:

Vous voulez trouver tous les codes postaux et les distances correspondantes dans un certain rayon de mile / kilomètre d'un autre code postal ou d'un point? Ce problème exigent latitude et longitude coordonnées pour résoudre. Géocodage l'adresse que vous donne latitude / longitude d'une adresse.

D'abord, vous aurez besoin d'une base de données de tous les codes postaux et leurs coordonnées de latitude et de longitude correspondant:

CREATE TABLE `zipcodes` (
  `zipcode` varchar(5) NOT NULL DEFAULT '',
  `city` varchar(100) NOT NULL DEFAULT '',
  `state` char(2) NOT NULL DEFAULT '',
  `latitude` varchar(20) NOT NULL DEFAULT '',
  `longitude` varchar(20) NOT NULL DEFAULT '',
  KEY `zipcode` (`zipcode`),
  KEY `state` (`state`)
)

Donc, une fois que vous avez la base de données que vous voulez trouver tous les codes postaux dans un rayon certain de mile d'un point central. Si le point central est un autre code postal, simplement interroger la base de données pour la latitude et la longitude coordonnées de ce code postal. Ensuite, le code est le suivant:

// ITITIAL POINT

$coords = array('latitude' => "32.8", 'longitude' => "-117.17");

//RADIUS

$radius = 30;

// SQL FOR KILOMETERS

$sql = "SELECT zipcode, ( 6371 * acos( cos( radians( {$coords['latitude']} ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( {$coords['longitude']} ) ) + sin( radians( {$coords['latitude']} ) ) * sin( radians( latitude ) ) ) ) AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance";

// SQL FOR MILES

$sql = "SELECT zipcode, ( 3959 * acos( cos( radians( {$coords['latitude']} ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( {$coords['longitude']} ) ) + sin( radians( {$coords['latitude']} ) ) * sin( radians( latitude ) ) ) ) AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance";

// OUTPUT THE ZIPCODES AND DISTANCES

$query = mysql_query($sql);

while($row = mysql_fetch_assoc($query)){

    echo "{$row['zipcode']} ({$row['distance']})<br>\n";

}

(Yahoo et Google offrent des services de géocodage gratuit.)

Était-ce utile?

La solution

Vous voulez faire quelque chose comme ceci:

SELECT zipcode FROM zipcodes WHERE DistanceFormula(lat, long, 4.808855, 52.406332) < $range

Il peut être lent si votre table de codes postaux est grande. Vous pouvez également consulter les extensions géospatiales pour MySQL.

Autres conseils

Vous devez utiliser ce qu'on appelle le Haversine formule :

$sql = "
    SELECT zipcode
    FROM zipcodes
    WHERE ".mysqlHaversine($lat, $lon, $distance)."
";

Et la formule:

function mysqlHaversine($lat = 0, $lon = 0, $distance = 0)
{
    if($distance > 0)
    {
        return ('
        ((6372.797 * (2 *
        ATAN2(
            SQRT(
                SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) *
                SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) +
                COS(latitude * (PI()/180)) *
                COS('.($lat*1).' * (PI()/180)) *
                SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2) *
                SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2)
                ),
            SQRT(1-(
                SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) *
                SIN(('.($lat*1).' * (PI()/180)-latitude*(PI()/180))/2) +
                COS(latitude * (PI()/180)) *
                COS('.($lat*1).' * (PI()/180)) *
                SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2) *
                SIN(('.($lon*1).' * (PI()/180)-longitude*(PI()/180))/2)
            ))
        )
        )) <= '.($distance/1000). ')');
    }

    return '';
}

En général, je ne pas utiliser le code sans comprendre la façon dont il fonctionne d'abord, mais je dois avouer cette fonction est un peu au-dessus de ma tête ...

Alors que la méthode de Captaintokyo est exacte, il est également assez lent. Je ne peux pas empêcher de penser qu'il serait plus avantageux d'utiliser une table temporaire de tous les codes postaux dont les limites sont dans la plage, puis d'affiner les résultats par la distance.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top