This was interesting... I was playing with my query. I was using the 2 query approach. First query gets the target zip's lat/long coordinates. Query 2 does the radius check and brings back all the goodies.
Splitting up this query made things worse. Here's the setup: Postgresql v7.3.4 (I believe), PHP v 4.3.8, zip distance calculated by C function built into Postgresql.
The queries (note: there's a query to fetch lat/long values - this query is not included in the timing):
Sub-select:
$query = 'SELECT zipponame, zipclass, zipcode, ziplong, ziplat, stateabrev, statename, countyname, zip.zipcounty, geodist(' . $lat . ', ' . $long . ', ziplat, ziplong) AS distance FROM zip INNER JOIN state ON state.fipsstate = zip.zipstate INNER JOIN county ON county.fipsstate = zip.zipstate and county.fipscounty = zip.zipcounty WHERE zipcode IN (SELECT zipcode FROM zip WHERE geodist(' . $lat . ', ' . $long . ', ziplat, ziplong) <= ' . $get['radius'] . ') ORDER BY geodist(' . $lat . ', ' . $long . ', ziplat, ziplong)';
Results: didn't return any data in an acceptable time frame.
Fetch zip codes first:
$ziplist = getZipCodeList($lat, $long, $get['radius']);
$query = 'SELECT zipponame, zipclass, zipcode, ziplong, ziplat, stateabrev, statename, countyname, zip.zipcounty, geodist(' . $lat . ', ' . $long . ', ziplat, ziplong) AS distance FROM zip INNER JOIN state ON state.fipsstate = zip.zipstate INNER JOIN county ON county.fipsstate = zip.zipstate and county.fipscounty = zip.zipcounty WHERE zipcode IN (' . $ziplist . ') ORDER BY geodist(' . $lat . ', ' . $long . ', ziplat, ziplong)';
This one worked. For 44137 and a 20 mile radius, it brought back the results in 9.5 seconds. Not good.
Combine query 2 and 3 together:
$query = 'SELECT zipponame, zipclass, zipcode, ziplong, ziplat, stateabrev, statename, countyname, zip.zipcounty, geodist(' . $lat . ', ' . $long . ', ziplat, ziplong) AS distance FROM zip INNER JOIN state ON state.fipsstate = zip.zipstate INNER JOIN county ON county.fipsstate = zip.zipstate and county.fipscounty = zip.zipcounty WHERE geodist(' . $lat . ', ' . $long . ', ziplat, ziplong) <= ' . $get['radius'] . ' ORDER BY geodist(' . $lat . ', ' . $long . ', ziplat, ziplong)';
Time is about 0.6 seconds for 44137 and a 20 mile radius. This is the current query I use on my page (http://www.rsbauer.com/zip/). I've left the timer up in case people would like to play with it.
Now do a zip of 44137 and 1000 miles and it takes about 17.5 seconds. Drawmack, you had mentioned for 1000 zips, your query takes about 20 seconds. So, the approach I'm using doesn't seem to be too bad, even though it IS checking the distance for each (42,000+) zip code.
Interesting stuff...
If people would like to see the C code (PostgreSQL flavor) for geodist(), let me know. I have it in C++ flavor for MySQL as well.