Setting up tables might otimize some applications, but there is another way to approach it also.
First you make a query to find the latitude north and south of the distance you are trying to isolate, and the longitude east and west, then pass those variables into your next sql statement. You could skip this query do it all in one query, but it would be making redundant calculations, so the extra query pays for itself.
When you make your sql statement to return the results, you include in your WHERE clause the lat and lon must be within the range of the variables you passed in from the first sql query. The excess calculations are then limited to only those needed to trim out the 'corners'.
I hope I explained that right. It does work and it is very fast, but you need to use MySql to compute the haversine or may find yourself somewhat bogged down.
This is the SQL statement I use to get the distance between two zip codes. This query is for only selecting between two zipcodes only. The code I used to do the radius calculations is on another page, this happened to be on the page I was working on when I decided to take a break l However, the haversine formulae works splendidly, and this query is the one I built all my distance functions from. (or in some cases trimmed from)
It accepts a lat and lon variable passed in from PHP ($l1 and $o1) and compares it to zip codes selected from the database for the member whos ID matches the variable passed in as $locate:
$sql="select
(7912 atan2(sqrt(pow((sin(((radians($l1))-(radians(z.lat)))/2)),2)+ cos((radians(z.lat))) cos((radians($l1))) pow((sin(((radians($o1))-(radians(z.lon)))/2)),2)), sqrt(1-(pow((sin(((radians($l1))-(radians(z.lat)))/2)),2)+ cos((radians(z.lat))) cos((radians($l1))) * pow((sin(((radians($o1))-(radians(z.lon)))/2)),2)))))
as distance
from zipcode_all z, member m
where $locate=m.member_id && m.zipcode=z.zipcode";