how do I write a query based on distance, its a bit hard to explain but heres what I am looking for
On websites like gum tree, there is an option which says "WITH IN MILES" +10 miles, +5 miles e.t.c.
How do I calculate the area based on the city or postcode provided by the user.
How will the query execute and return results based on this search. thank you.
Im using PHP and MYSQL for this project.
Distances like that are calculated using the haversine formula using the latitude and longitude of two points. The lat and long data is widely available through simple Google searches.
Related
I have table "vehicle_location" and "coordinates" column in table datatype is geomatry
and in my controller i am getting lat and long and radius in request so i want to find vehicle location data using radius
Have a look at the formula explained on Wikipedia: https://en.wikipedia.org/wiki/Great-circle_distance
You'll find someone asking about the same question here: Measuring the distance between two coordinates in PHP
Ideally, it would be good to be able to reduce the calculation of distances to only cars that are not to far from your location. So typically, I would start by an SQL query that only returns the vehicules which have latitude and longitude values in the nearby, according to the given radius.
Then, in a second step, you can calculate all the distances between these cars and your position, with the algorithm (which takes some calculation time) and sort them after.
The ideal thing to do is to try and do the calculation directly in SQL if possible, so that you can sort them and filter them with the radius. If it gets to complicated then do the calculation and sorting in PHP.
I have an SQL database containing hotel information, some of which is the geocoded lat/lng generated by Googles geocoder.
I want to be able to select (directly using an SQL query) all the hotels within a certain range. This range will never be more than 50km so I dont need to go as detailed as alot of answers on here are suggesting (taking into account earth curvature and the fact its not a perfect sphere isnt an issue over the distances im searching).
Im thinking a simple Pythagorian formula would suffice, but I dont know what the latitude and longitude figures represent (and therefore how to convert to metres) and also ive read on a couple of 'simple' solutions to my problem that there are issues with their formulas and calculating distances between two locations either side of the meridian line (as I am based in London this will be a big issue for me!!)
Any help would be great, thankyou!
----Helpful Information-----
My database stores the geocoded data in the following format:
geo_lat: 51.5033630,
geo_lon; -0.1276250
This is a select clause that will get your distance into kilometers. From there you can use a where clause to filter it down to less than 25 kilometers or whatever you want. If you want it in miles just take off the * 1.609344 conversion.
$latitude = [current_latitude];
$longitude = [current_longitude];
SELECT
((((acos(sin((".$latitude."*pi()/180)) * sin((`geo_lat`*pi()/180))+cos((".$latitude."*pi()/180)) * cos((`geo_lat`*pi()/180)) * cos(((".$longitude."- `geo_lon`)* pi()/180))))*180/pi())*60*1.1515) * 1.609344) as distance
FROM
[table_name]
WHERE distance
You can use a simple map projection and straight distances for example equirectangular projection. In the formula on this website you can also use a simplier formula without the square root:http://www.movable-type.co.uk/scripts/latlong.html. Of course you can use a bounding box to filter the query:How to calculate the bounding box for a given lat/lng location?, https://gis.stackexchange.com/questions/19760/how-do-i-calculate-the-bounding-box-for-given-a-distance-and-latitude-longitude.
In an app I'm building, One of the features i'd like users to be able to discover people around them easily. I'm using the GPS to get the latitude and longitude, then storing that information in the mysql db along with the other user information under a column for latitude and another with the longitude. What's would the best practice be to do a query that looks at the person whos making the query's information...and then have it find the closest possible relatable lat and longitude then start there and limit it to 24 results? And furthermore, how would I remember where it stopped so I could allow another query to start where it left off and return more getting further and further away
Basically, to generalize how can I do a mysql query that starts as close as it can to 2 latitude and longitude points that I supply and then have it grab the next 24 sorted by closest to furthest?
I feel like its going to be hard to do because its being based on 2 columns. Is there a way I should/could be combining the GPS values into 1 column so it will be easy to find relative distance?
Maybe I could somehow get the zip code (but then that might cause non US problems). I'm not sure. I'm stuck.
Just search for "Haversine Formula" here on Stackoverflow and you will find several related questions.
As #cdonner mentioned, there are a number of resources for the Haversine formula which you use to transform lat and long into distance. You would pass in a distance variable based on how your formula is set up, usually based on miles and run your query starting at the closest radius. Using a php loop, you can simply increase the distance and re-run the query until you get the desired number of results. And do check out that google link re #Maleck13 as well, very helpful.
I have a system which will return all users from the database and order the results by lowest distance from a reference zip code.
For example: User will come on the site, enter zip code and it will return him all other users who are nearest to his zip (ascending order)
How am i doing this now and why is it a problem ?
The system contains more than 30 million users and their zipcodes. I am retreiving all the users in a particular state and city (narrows the dataset down to about 10,000).
This is where the problem actually happens. Now, all the result sent by mysql (10,000) rows to PHP are sent to a zipcode calculator library which calculates this distance between the base zip code and user's zip code - 10,000 times. Then orders the result by the zip code nearest.
As you can see, this is very badly optimized code. And the 10,000 records are looped through twice. Not to mention the amount of RAM each httpd process takes just transferring data to and fro mysql.
What I would like to ask the gurus in here that is there anyway to optimize this ?
I have a few ideas of my own, but i'm not sure how efficient they are.
Try to do all the zipcode calculation and ordering in mysql itself and return the paginated number of rows.
For this, i will need to move the distance between zipcode calculation logic to a stored procedure. This way I am preventing the processing of 10,000 records in PHP. However, there is still a problem. I would not need to calculate distance for zip codes which have already been calculated (for 2 users having the same zip code).
Secondly, how do i order rows in mysql using a stored procedure ?
What do you guys think ? Is this a good way ? Can i expect a performance boost using this ?
Do you have any other suggestions ?
I know this question is huge, and i really appreciate the time you have taken to read till the end. I would really like to hear your thoughts about this.
As I'm not overly familiar with PHP or MySQL, I can only give some basic tips but they should help. This also assumes you have no direct way of interfacing with the zip library from MySQL.
First, as it's doubtful that you have 10k zip codes in a city, take your existing query and do something like
SELECT DISTINCT ZipCode FROM Users WHERE ...
This will probably return a few dozen zip codes max, and no duplicates. Run this through your zip code library. That library itself is probably a source of slowness, as it has to look up the zip codes, and do a bunch of fancy trig to get actual distance. Take the results of this, and insert it into a temp table with just the zip code and the distance.
Once done with that list, have another query that gets the rest of the user data you want, and JOIN into the the temp table on zip code to get your distance.
This should give you quite a large speedup. You can do whatever paging you need in the second query after the results have been calculated. And no more looping through 10k rows.
I suggest that you narrow the latitude and longitude ranges before you compute the accurate distance for filtering and sorting purposes.
What I mean is if you do a full table scan and compute distances for all zip codes in the database relative to your reference point, it will be very slow.
Instead, filter zipcode by proximity. I mean if you have latitude 10 and longitude 20, first compute the maximum angular range for the proximity you want. Lets say you want a proximity range of 10 miles. That may translate into 0.15 degrees. So you need to filter you zip codes first latitude between 10-0.15 and 10+0.15 and longitude between 20-0.15 and 20+0.15 .
Only after that you include the accurate distance clause in your SQL query condition. That will be much faster because you no longer do full scan and you can eventually use range indexes on longitude and latitude fields.
To translate miles into degrees find the narrow range, keep in mind that the Earth has , approximately 25,000 miles of perimeter, divide 25000 by 360 degrees which gives 70 miles per degree. If you want a range of 10 miles, your range in degrees will be at most 0.15 degrees.
Keep in mind that these calculations are not accurate (the Earth is not exactly well rounded) but that is not important. What is important is that you find a degree range value that is higher than the really accurate value.
If you can get the latitude and longitude for all zipcodes into MySQL, or have an easy way of fetching the lat/long for your base zipcode and feeding it into your MySQL query, then you can order your 10k users by distance inside MySQL. There is a very similar question and answer here which gives you the correct math for the distance function. You may also want to investigate Mysql spatial extensions which would let you insert and index your lat/longs as 2D POINT data.
In my database I have a list of places and for each I have a street name and number, postcode, city and county. Some of them have a latitude and longitude location.
And I have the geo location of the city centre for example. I would like to display only the places that are within X miles of the city centre on a google map.
Incase this would need a geo location for each of my places to work, I could perhaps set up a script to use google maps api to use geocoding to get a geo location for all my places and update the database with the lat/lng. Then I would have a database full of lat and long locations to work from.
Once all the places have a lat/lng then maybe mysql can return the within range addresses?
This is not hard once you have lat / long data, and if somebody gives you the great circle distance formula in mySQL format.
#maggie gave a good reference. How to efficiently find the closest locations nearby a given location
Indexing strategy: Keep in mind that one minute of latitude (1/60 degree) is one nautical mile, or 1.1515 statute miles (approximately) all over the world. So index your latitude column and do your search like this. (If you're in the part of the world that uses km, you can convert; sorry for the Old-British-Empire-Centric answer, but they did define the nautical mile.)
WHERE mylat BETWEEN column.lat-(myradius*1.1515) AND column.lat+(myradius*1.1515)
AND (the big distance formula) <= myradius
This will give you both decent data base indexing AND reasonably accurate distance circles.
One extra refinement: You can index longitude too. The trouble is that ground distance isn't directly related to longitude. At the equator it is one nautical mile per minute, but it gets smaller, and at the poles there are singularities. So, you can add another term to your WHERE. It gives correct results but isn't as selective as latitude indexing. But it still helps the indexing lookup, especially if you have lots of rows to sift through. So you get:
WHERE mylat BETWEEN column.lat-(myradius*1.1515) AND column.lat+(myradius*1.1515)
AND mylon BETWEEN column.lon-(myradius*1.1515) AND column.lon+(myradius*1.1515)
AND (the big distance formula) < myradius
Most likely you want to use a space-filling-curve or a spatial index to reduce your 2D problem to a 1D problem. For example you can combine the lat/long pair with a z-curve or a hilbert curve. I use for myself a hilbert curve to search for postcodes. You can find my solution at phpclasses.org ( hilbert-curve ).