I Tried using the above code, and the answers were off by too much when the distance between points was in the 20-30 mile range, and I'm ok with a few miles of error. Talked with a mapping buddy of mine and we came up with this one instead. The code is python, but you can translate it pretty easily. In order to avoid the constant conversion to radians, I redid my database, converting the lat/lng points from degrees to Radians. The nice part about this is that the largest part of the math is mostly done once.
ra = 3963.1906 # radius @ equator in miles, change to km if you want distance in km
rb = 3949.90275 # radius @ poles in miles, change to km if you want distance in km
ra2 = ra * ra
rb2 = rb * rb
phi = self.lat
big_ol_constant = (math.pow(ra2*math.cos(phi), 2) + pow(rb2*math.sin(phi), 2))/ (pow(ra*math.cos(phi), 2) + pow(rb*math.sin(phi), 2))
sqlWhere = "%(distance)g > sqrt((power(lat - %(lat)g,2) + power(lng-%(lng)g,2)) * %(big_ol_constant)g)" % {
'big_ol_constant': big_ol_constant, 'lat': self.lat, 'lng': self.lng, 'distance': distance}
# This is the Django portion of it, where the ORM kicks in. sqlWhere is what you would put after the WHERE part of your SQL Query.
qs = ZipData.objects.extra(where=[sqlWhere]);
Seems to be very accurate when distance apart is small, and within 10 miles or so as the distance grows to 200 miles, (of course by then, you have issues with "as the crow flies" vs "paved roads")
An extra note, is that you can gets LOTS of geo data related to postal codes at link text and they even have some webservice APIs you can use as well.