MySQL selezionare zipcodes all'interno x km / miglia nel raggio d'azione di y
-
26-09-2019 - |
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.)
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.