Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

select within 20 kilometers based on latitude/longitude

Tags:

php

select

mysql

i have a mysql table structured as per the example below:

POSTAL_CODE_ID|PostalCode|City|Province|ProvinceCode|CityType|Latitude|Longitude
7|A0N 2J0|Ramea|Newfoundland|NL|D|48.625599999999999|-58.9758
8|A0N 2K0|Francois|Newfoundland|NL|D|48.625599999999999|-58.9758
9|A0N 2L0|Grey River|Newfoundland|NL|D|48.625599999999999|-58.9758

now what i am trying to do is create a query that will select results within selected kilometers of a searched location

so lets say they search for "grey river" and select "find all results within 20 kilometers"

it should obviously select "grey river", but it should also select all locations within 20 kilometers of grey river based on the latitudes and longitudes.

i really have no idea how to do this. i've read up on the haversine formula but have no idea how to apply this to a mysql SELECT.

any help would be much appreciated.

like image 953
scarhand Avatar asked Aug 02 '11 22:08

scarhand


People also ask

How do you convert latitude and longitude to kilometers?

The approximate conversions are: Latitude: 1 deg = 110.574 km. Longitude: 1 deg = 111.320*cos(latitude) km.

What is the distance of 1 of longitude?

One-degree of longitude equals 288,200 feet (54.6 miles), one minute equals 4,800 feet (0.91 mile), and one second equals 80 feet.

What is my latitude and longitude?

Android: Open Google Maps; it will zoom to your approximate location. Press and hold on the screen to drop a pin marker. Click on the dropped pin; latitude and longitude will be displayed below the map. If you don't have Google Maps, you can install a free GPS app before heading to your site.


2 Answers

SELECT  *
FROM    mytable m
JOIN    mytable mn
ON      ACOS(COS(RADIANS(m.latitude)) * COS(RADIANS(mn.latitude)) * COS(RADIANS(mn.longitude) - RADIANS(m.longitude)) + SIN(RADIANS(m.latitude)) * SIN(radians(mn.latitude))) <= 20 / 6371.0
WHERE   m.name = 'grey river'

If your table is MyISAM you may want to store your points in a native geometry format and create a SPATIAL index on it:

ALTER TABLE mytable ADD position POINT;

UPDATE  mytable
SET     position = POINT(latitude, longitude);

ALTER TABLE mytable MODIFY position NOT NULL;

CREATE SPATIAL INDEX sx_mytable_position ON mytable (position);

SELECT  *
FROM    mytable m
JOIN    mytable mn
ON      MBRContains
                (
                LineString
                        (
                        Point
                                (
                                X(m.position) - 0.009 * 20,
                                Y(m.position) - 0.009 * 20 / COS(RADIANS(X(m.position)))
                                ),
                        Point
                                (
                                X(m.position) + 0.009 * 20,
                                Y(m.position) + 0.009 * 20 / COS(RADIANS(X(m.position))
                                )
                        ),
                mn.position
                )
        AND ACOS(COS(RADIANS(m.latitude)) * COS(RADIANS(mn.latitude)) * COS(RADIANS(mn.longitude) - RADIANS(m.longitude)) + SIN(RADIANS(m.latitude)) * SIN(radians(mn.latitude))) <= 20 / 6371.0
WHERE   m.name = 'grey river'
like image 85
Quassnoi Avatar answered Oct 01 '22 10:10

Quassnoi


SELECT `s`.suburb_id,`s`.suburb_name,`s`.lat,`s`.long, (((acos(sin(($lat*pi()/180)) * sin((s.lat*pi()/180))+cos(($lat*pi()/180)) * cos((s.lat*pi()/180)) * cos((($long - s.long)*pi()/180))))*180/pi())*60*1.1515*1.609344) AS distance FROM (`mst_suburbs` as s) HAVING distance <= 20 ORDER BY `s`.suburb_id DESC

This query works for me to get all the lat,long between 12 km distance.I have mst_suburbs is may table which having the lat and long column.$lat and $long are my two php variable .and I am passing the desired lat,long to get the nearest 12km lat long list from the mst_suburb. You just need to change the name of the column according to your table and pass the lat,long to query.

like image 44
vaibhav kulkarni Avatar answered Oct 01 '22 09:10

vaibhav kulkarni