The distance between two coordinates, how can I simplify this and / or use another technique?

I need to write a query that allows me to find all the locations within the range (Miles) from the provided location.

The table looks something like this:

id  |  name  |  lat  |  lng 

So, I am doing research and found: this is my sql presentation

I tested it on a table with 100 rows and get a lot more! - Must be scalable.

I first tried something simpler:

//just some test data this would be required by user input    
set @orig_lat=55.857807; set @orig_lng=-4.242511; set @dist=10;

SELECT *, 3956 * 2 * ASIN(
          SQRT( POWER(SIN((orig.lat - abs(dest.lat)) * pi()/180 / 2), 2) 
              + COS(orig.lat * pi()/180 ) * COS(abs(dest.lat) * pi()/180)  
              * POWER(SIN((orig.lng - dest.lng) * pi()/180 / 2), 2) )) 
          AS distance
  FROM locations dest, locations orig
 WHERE orig.id = '1'
HAVING distance < 1
 ORDER BY distance;

This returns lines around 50 ms , which is very good! However, this will significantly slow down the growth of lines.

EXPLAIN shows this only using the obvious PRIMARY key.


Then after reading the related article above . I tried something like this:

// defining variables - this when made into a stored procedure will call
// the values with a SELECT query.
set @mylon = -4.242511;
set @mylat = 55.857807;
set @dist = 0.5;

-- calculate lon and lat for the rectangle:
set @lon1 = @mylon-@dist/abs(cos(radians(@mylat))*69);
set @lon2 = @mylon+@dist/abs(cos(radians(@mylat))*69);
set @lat1 = @mylat-(@dist/69); 
set @lat2 = @mylat+(@dist/69);

-- run the query:

SELECT *, 3956 * 2 * ASIN(
          SQRT( POWER(SIN((@mylat - abs(dest.lat)) * pi()/180 / 2) ,2)
              + COS(@mylat * pi()/180 ) * COS(abs(dest.lat) * pi()/180)
              * POWER(SIN((@mylon - dest.lng) * pi()/180 / 2), 2) ))
          AS distance
  FROM locations dest
 WHERE dest.lng BETWEEN @lon1 AND @lon2
   AND dest.lat BETWEEN @lat1 AND @lat2
HAVING distance < @dist
 ORDER BY distance;

240 , , . , . EXPLAIN lat, lng PRIMARY PRIMARY.

???

, lat lng POINT(); , , ?

!

!

-Stefan


UPDATE:

, , :

abs() lat. id WHERE , . , - .

EXPLAIN , lng 180 , .

+3
5

!

( ), . , () // .

MySQL OpenGIS, / ( , ) / ( - ).

PostGis PostgreSql :

( b, , 1000 a 123)

select 
    myvalue
from 
    tablea, tableb
where 
    st_dwithin(tablea.the_geom, tableb.the_geom, 1000)
and
    tablea.id = 123
+2

, , 1 @dist orig @orig_lat @orig_lon.

, , , . - orig.id = 1, , orig dest ( dest.id = 1; , AND orig.id != dest.id). HAVING, GROUP BY, . HAVING - , HAVING ( ) .

, COS (ABS (x)) === COS (x), , ABS(). , , - - .

- 69 - (, ), 3956 - .

, , . .

dest.id = 1 ; , , , . . .

HAVING WHERE.

, ...

+2

. ( ), .

.,, -, - .

SO , : https://stackoverflow.com/search?q=geohash

0

If you are only interested in short distances, you can approximate the geographic grid with a rectangular grid.

SELECT *, SQRT(POWER(RADIANS(@mylat - dest.lat), 2) +
               POWER(RADIANS(@mylon - dst.lng)*COS(RADIANS(@mylat)), 2)
              )*@radiusOfEarth AS approximateDistance

You can make this even more efficient by storing radians instead (or in addition) of degrees in your database. If your requests may overlap with the 180 ° meridian, extra care will be required here, but many applications do not have to deal with these locations. You can also try changing POWER(x )to x *x, which can be calculated faster.

0
source

Source: https://habr.com/ru/post/1786518/


All Articles