Domanda

Nota. Anche se io uso un database di codice postale con zipcodes olandese, questa domanda è paese indipendente

Ho un database con ogni codice postale nei Paesi Bassi + sua coordinate X e Y (latitudine / longitudine).

ho per esempio codice postale: $baseZipCode = 1044; con le seguenti coordinate:

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

Ora, vorrei trovare tutti gli altri zipcodes con $range da $baseZipCode.

Ad esempio:

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

Il problema è che la terra non è del tutto tondo. Trovo un sacco di tutorial con i calcoli from a to b ma non è questo quello che mi serve.

Qualcuno ha qualche idea?


Aggiorna Grazie a Captaintokyo ho trovato questo:

Vuoi trovare tutte zipcodes e distanze corrispondenti una determinata distanza miglio / chilometro da un altro codice postale o il punto? Questi problemi richiedono coordinate di latitudine e longitudine da risolvere. Geocoding l'indirizzo consente di latitudine / longitudine coordinate da un indirizzo.

In primo luogo sarà necessario un database di tutti zipcodes ei corrispondenti coordinate di latitudine e longitudine:

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`)
)

Quindi, una volta che hai il database che si desidera trovare tutte le zipcodes entro un certo raggio di miglia di un punto centrale. Se il punto centrale è un altro codice postale, semplicemente interrogare il database per la latitudine e longitudine di tale codice postale. Quindi il codice è il seguente:

// 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";

}

(Sia Yahoo e Google offrono servizi di geocodifica liberi.)

È stato utile?

Soluzione

Si vuole fare qualcosa di simile:

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

Può essere lento se la tabella di codici di avviamento postale è grande. Si consiglia inoltre di controllare le estensioni geospaziali per MySQL.

Altri suggerimenti

Devi usare qualcosa chiamato il Haversine formula :

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

E la formula:

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 '';
}

Di solito Non faccio uso di codice senza la comprensione del modo in cui funziona un primo momento, ma devo confessare questa funzione è un po 'sopra la mia testa ...

Mentre il metodo di Captaintokyo è preciso, è anche abbastanza lento. Non posso fare a meno di pensare che sarebbe più vantaggioso utilizzare una tabella temporanea di tutte le zipcodes i cui confini sono all'interno della gamma, poi per perfezionare questi risultati dalla distanza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top