Php/MySQL Zip Code Proximity Search

php/mysql zip code proximity search

Here is the best way I have found. Of course it will require that you have all of your zipcodes lat/lon encoded in the database.

// get all the zipcodes within the specified radius - default 20
function zipcodeRadius($lat, $lon, $radius)
{
$radius = $radius ? $radius : 20;
$sql = 'SELECT distinct(ZipCode) FROM zipcode WHERE (3958*3.1415926*sqrt((Latitude-'.$lat.')*(Latitude-'.$lat.') + cos(Latitude/57.29578)*cos('.$lat.'/57.29578)*(Longitude-'.$lon.')*(Longitude-'.$lon.'))/180) <= '.$radius.';';
$result = $this->db->query($sql);
// get each result
$zipcodeList = array();
while($row = $this->db->fetch_array($result))
{
array_push($zipcodeList, $row['ZipCode']);
}
return $zipcodeList;
}

You should be able to just drop in this function. Pass it the $lat and $lon of the zipcode you want the radius for, include the optional radius, and get a list of zipcodes back.

You could very easily modify this to get all users where zipcode IN (radius_sql) and get your list users back.

Happy Coding!

Sorting zip code proximity search by distance (php/mysql)

You could use something like

$iDistance = 20;
$iRadius = 6371; // earth radius in km
$iRadius = 3958; // earth radius in miles
$fLat = x.y; // Your position latitude
$fLon = x.y; // Your position longitude

$strQuery = "
SELECT
*,
$iRadius * 2 * ASIN(SQRT(POWER(SIN(( $fLat - abs(pos.lat)) * pi() / 180 / 2),2) +
COS( $fLat * pi()/180) * COS(abs(pos.lat) * pi() / 180) * POWER(SIN(( $fLon - pos.lon) *
pi() / 180 / 2), 2) )) AS distance
FROM user_zip_codes pos
HAVING distance < $iDistance
ORDER BY distance";

where you have to fetch your lat/lon value before using the SQL. This works for me

Find the nearest zip code location in PHP / MYSQL

See this Fastest Way to Find Distance Between Two Lat/Long Points

Basically you compute the distance to your base latlon, sort by shortest distance, and get the item on top. You can also do this in code if you don't want to bother having complex queries.

Keywords are "great circle distance" and "haversine formula"

EDIT

Let's say I have a database of vet clinics in LA

Limehouse Veterinary Clinic   34.1534500122    -118.3630599976
LA Pet Clinic 34.0838623047 -118.3284454346
Bestfriends Animal Hospital 34.1692466736 -118.3970489502

And my base coordinates is in hollywood lat 34.092324, lon -118.337122

haversine formula needs coords in radians instead of degrees.

There are 2 pi radians in 360 degrees so
y radians = 6.28319 * x degrees / 360 (solving for y)

The following is the haversine formula where r in 2 r arcsin is the earth's radius: 6,371,000 meters

-- haversine
-- latdif londif
-- 2 r arcsin [ sqrt[ sin^2(------) + cos(lat1) * cos(lat2) * sin^2(------) ] ]
-- 2 2

Therefore to get the nearest clinics near my location, I can use this query as a translation of the above formula

select 
name,
2 * 6371000 * ASIN(
sqrt(
SIN(6.28319 * (34.092324 - lat) / 360 / 2) * SIN(6.28319 * (34.092324 - lat) / 360 / 2)
+
COS( 6.28319 * 34.092324 / 360 ) * COS( 6.28319 * lat / 360 )
*
SIN(6.28319 * (-118.337122 - lon) / 360 / 2) * SIN(6.28319 * (-118.337122 - lon) / 360 / 2)
)
)
as dist_in_meters
from locations ORDER BY dist_in_meters;

Giving me

name                              dist_in_meters
LA Pet Clinic 1234.3897096551932
Limehouse Veterinary Clinic 7204.075434291492
Bestfriends Animal Hospital 10177.689847331932

users near a specific zip code: PHP mysql

If You have zip code in $items then i think you don't need $itemsz for all customer zipcodes.

First you need to format $items array to like this :

$zips = (12345,12346,12347,12348)

Then just run a query like this in customer:

Select * from customer where customer.zipcode IN $zips

demo: https://eval.in/84652

SAMPLE code:

$items =array( '0' => array( 'zip_code' => 13121, 'latitude' => 43.483379, 'longitude' => -76.315044, 'city' => 'New Haven', 'state' => 'NY', 'county' => 'Oswego' ), '1' => array( 'zip_code' => 13126, 'latitude' => 43.465388 ,'longitude' => -76.342172 ,'city' => 'Oswego' ,'state' => 'NY', 'county' => 'Oswego' ) );

$strzipCodes="";
foreach($items as $item){

$strzipCodes .= $item['zip_code']." ,";

}
$strzipCodes = rtrim($strzipCodes,',');

$sql ="SELECT * FROM customer where zip IN(".$strzipCodes.")";
echo $sql;
// then execute query we will get all users inside those zipcodes

I think you get the idea.

Searching by Zip Code proximity - MySql

You should build a table that has each zip code with an associated latitude and longitude. When someone enters a zip and a distance, you calculate the range of latitudes and longitudes that fall within it, and then select all the zip codes that fall within that bounding box. Then you select any stores that have zip codes within that set, and calculate their distance from the provided zip and sort by it. (Use the haversine formula for calculating the distance between points on a globe)

If speed is your main concern, you might want to precompute all the distances. Have a table that contains a store zip code column, the other zip code, and a distance column. You can restrict the other zip codes to zip codes within a certain distance (say 100 miles, or what have you) if you need to cut down on rows. If you don't restrict the links based on distance, you'll have a table with > 700 million rows, but you could certainly do fast lookups.

MySQL Function to Determine Zip Code Proximity / Range

This nifty lil mySQL function that I wrote should definitely do the trick for you.

BEGIN
DECLARE x decimal(18,15);
DECLARE EarthRadius decimal(7,3);
DECLARE distInSelectedUnit decimal(18, 10);

IF originLatitude = relativeLatitude AND originLongitude = relativeLongitude THEN
RETURN 0; -- same lat/lon points, 0 distance
END IF;

-- default unit of measurement will be miles
IF measure != 'Miles' AND measure != 'Kilometers' THEN
SET measure = 'Miles';
END IF;

-- lat and lon values must be within -180 and 180.
IF originLatitude < -180 OR relativeLatitude < -180 OR originLongitude < -180 OR relativeLongitude < -180 THEN
RETURN 0;
END IF;

IF originLatitude > 180 OR relativeLatitude > 180 OR originLongitude > 180 OR relativeLongitude > 180 THEN
RETURN 0;
END IF;

SET x = 0.0;

-- convert from degrees to radians
SET originLatitude = originLatitude * PI() / 180.0,
originLongitude = originLongitude * PI() / 180.0,
relativeLatitude = relativeLatitude * PI() / 180.0,
relativeLongitude = relativeLongitude * PI() / 180.0;

-- distance formula, accurate to within 30 feet
SET x = Sin(originLatitude) * Sin(relativeLatitude) + Cos(originLatitude) * Cos(relativeLatitude) * Cos(relativeLongitude - originLongitude);

IF 1 = x THEN
SET distInSelectedUnit = 0; -- same lat/long points
-- not enough precision in MySQL to detect this earlier in the function
END IF;

SET EarthRadius = 3963.189;
SET distInSelectedUnit = EarthRadius * (-1 * Atan(x / Sqrt(1 - x * x)) + PI() / 2);

-- convert the result to kilometers if desired
IF measure = 'Kilometers' THEN
SET distInSelectedUnit = MilesToKilometers(distInSelectedUnit);
END IF;

RETURN distInSelectedUnit;
END

It takes originLatitude, originLongitude, relativeLatitude, relativeLongitude, and measure as parameters. Measure can simply be Miles or Kilometers

Hope that helps!

mySQL select zipcodes within x km/miles within range of y

You want to do something like this:

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

It may be slow if your table of zip codes is large. You may also want to check out the geospatial extensions for MySQL.

Merge two MySQL query and get distance between two zip codes

You can use the spacial functions and spacial type columns http://dev.mysql.com/doc/refman/5.5/en/spatial-extensions.html

Here it's a great example to use spacial functions!
http://www.mysqlperformanceblog.com/2013/10/21/using-the-new-spatial-functions-in-mysql-5-6-for-geo-enabled-applications/

Or you can define a custom function


CREATE DEFINER=`test`@`%` FUNCTION `geoDistance`(`lon1` DOUBLE, `lat1` DOUBLE, `lon2` DOUBLE, `lat2` DOUBLE)
RETURNS double
LANGUAGE SQL
DETERMINISTIC
NO SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE v DOUBLE;
SELECT cos(radians(lat1))
* cos(radians(lat2))
* cos(radians(lon2) - radians(lon1))
+ sin(radians(lat1))
* sin(radians(lat2)) INTO v;
RETURN IF(v > 1, 0, 6371000 * acos(v));
END

then call


SELECT geoDistance(X(point1), Y(point1), X(spoint2), Y(point2))
result comes in meters



Related Topics



Leave a reply



Submit