2

I have a SQL database set of places to which I am assigned coordinates (lat, long). I would like to ask those points that lie within a radius of 5km from my point inside. I wonder how to construct a query in a way that does not collect unnecessary records?

lukassz
  • 3,135
  • 7
  • 32
  • 72
  • 1
    What database engine and version? What have you tried so far? – duffn Sep 06 '15 at 20:13
  • I use MySQL database based on Boot Spring / Hibernate. I do not know if I need to download all the records and then calculate their distance from the center point if I can immediately pull out the inquiry. – lukassz Sep 06 '15 at 20:25
  • What is the precision you need? can you assume that 0.05 in lat,long are approximately 5 km ? – Balinti Sep 06 '15 at 20:28
  • |I want to find all the points from the database that are eg. In a radius of 5km from my predetermined center point. – lukassz Sep 06 '15 at 20:32
  • Here is a write up of this application. http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/ – O. Jones Sep 07 '15 at 01:22
  • or use geospatial extensions for the datastore, such as shown on http://www.datanucleus.org/products/accessplatform_4_2/datastores/rdbms_spatial_types.html and then such a calculation is simple, because there are methods to do just that – Neil Stockton Sep 07 '15 at 07:21

2 Answers2

2

Since you are talking about small distances of about 5 km and we are probably not in the direct vicinity of the north or south pole we can work with an approximated grid system of longitude and latitude values. Each degree in latidude is equivalent to a distance of km_per_lat=6371km*2*pi/360degrees = 111.195km. The distance between two longitudinal lines that are 1 degree apart depends on the actual latitude:

km_per_long=km_per_lat * cos(lat)

For areas here in North Germany (51 degrees north) this value would be around 69.98km.

So, assuming we are interested in small distances around lat0 and long0 we can safely assume that the translation factors for longitudinal and latitudinal angles will stay the same and we can simply apply the formula

SELECT 111.195*sqrt(power(lat-@lat0,2)
                   +power(cos(pi()/180*@lat0)*(long-@long0),2)) dist_in_km FROM tbl

Since you want to use the formula in the WHERE clause of your select you could use the following:

SELECT * FROM tbl 
WHERE 111.195*sqrt(power(lat-@lat0,2)
                  +power(cos(pi()/180*@lat0)*(long-@long0),2)) < 5

The select statement will work for latitude and longitude values given in degree (in a decimal notation). Because of that we have to convert the value inside the cos() function to radians by multiplying it with pi()/180.

If you have to work with larger distances (>500km) then it is probably better to apply the appropriate distance formula used in navigation like

cos(delta)=cos(lat0)*cos(lat)*cos(long-long0) + sin(lat0)*sin(lat)

After calculating the actual angle delta by applying acos() you simply multiply that value by the earth's radius R = 6371km = 180/pi()*111.195km and you have your desired distance (see here: Wiki: great circle distance)

Update (reply to comment):

Not sure what you intend to do. If there is only one reference position you want to compare against then you can of course precompile your distance calculation a bit like

SELECT @lat0:=51,@long0:=-9;  -- assuming a base position of: 51°N 9°E
SELECT @rad:=PI()/180,@fx:=@rad*6371,@fy:=@fx*cos(@rad*@lat0);

Your distance calculation will then simplify to just

SELECT @dist:=sqrt(power(@fx*(lat-@lat0),2)+power(@fy*(long-@long0),2))

with current positions in lat and long (no more cosine functions necessary). It is up to you whether you want to store all incoming positions in the database first or whether you want to do the calculations somewhere outside in Spring, Java or whatever language you are using. The equations are there and easy to use.

Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
  • I want to use it in the Boot Spring applications using Hibernate. Does it pay to count the distance directly in the database? Is it better to get all the records from the database and then select them? – lukassz Sep 08 '15 at 11:22
-1

I would go with Euklid. dist=sqrt(power(x1-x2,2)+power(y1-y2,2)) . It works everywhere. Maybe you have to add a conversion to the x/y-coordinates, if degrees can't be translated in km that easy.

Than you can go and select everything you like WHERE x IS BETWEEN (x-5) AND (x+5) AND y IS BETWEEN (y-5) AND (y+5) . Now you can check the results with Euklid.

With an optimisation of the result order, you can get better results at first. Maybe there's a way to take Euklid to SQL, too.

queuverflow
  • 159
  • 9
  • Cartesian distance is unsuited to lat-lon distance calculations except for locations very close to one another and the equator. – O. Jones Sep 07 '15 at 01:18
  • Well, in my opinion, 5km is very close. And, as I said, there might be a need for a conversion, which cars10 elaborated very well ;-) – queuverflow Oct 20 '15 at 20:01