I have a MySQL database that looks as such:
Postcode int(4),
City varchar,
State varchar,
Latitude decimal(7,4),
Longitude decimal(7,4)
I want the user to enter their post code (1660 for example) and a radius of x (lets say 10) miles or kilometers. When they hit search, I want to return a list of all the cities within that radius. I have a database that contains all of the post codes, cities, latitudes, longitudes etc. of all areas within Australia.
If you could sacrifice some precisions (by selecting cities within a rectangle area 10 miles from post code 1660), then the solution can be as simple as:
Find out the latitude and longitude of post code 1660
Calculate the top left and bottom right of the rectangle area (10 miles to the left and top, 10 miles to the bottom and right)
Use the query like: select city from table where latitude between bottom_right_latitude and top_left_latitude and longitude between top_left_longitude and bottom_right_longitude
If it has to be precisely radius 10 miles (which means the area is a circle), then the solution will be very complicated, couldn't do it in a single query I afraid. You need to think about some helper columns and use the distance and bearing calculations formulas to do it.
Reference: Calculate distance, bearing and more between Latitude/Longitude points
Related
I have a MySQL table of lat/lon (think of a school campus or shopping mall).
Each location (school/mall) can have dozens of GPS positions stored in the table. All locations are captured using a mobile app and these locations can represent everything from entrances to specific rooms (conference) to easily identifiable locations such as elevators.
A user submits a request (i.e. janitor cleanup on isle 6) and I need to make sure the request (cleanup) being submitted is within the geofence established by finding the 4 points furthest away from each other for that location.
Currently we're using a Haversine search but we want to convert this to a fenced in system. What we can't do is build a separate geofence table.
I've googled around and not found anything (I'm probably not using the correct terms). How do I build that query?
At the first level of approximation, you can scan for a bounding box.
Say you have a loc table with loc_id, lat, lng columns.
And say your candidate point has the position #ptLat, #ptLng.
Compute the bounding boxes for each location. This works fine with latitude and longitude unless you're within a few degrees of the north or south pole or near 180° longitude.
SELECT loc_id, MAX(lat) north, MAX(lng) east, MIN(lat) south, MIN(lng) west
FROM loc
GROUP BY loc_id
This is fast if you have an index on (loc_id, lat, lng). It's also fast because you can avoid all the trig functions in the Great Circle calculation.
Once you have the bounding box, you can decide whether your candidate point is inside it.
Then you can do
SELECT loc_id
FROM (
SELECT loc_id, MAX(lat) north, MAX(lng) east, MIN(lat) south, MIN(lng) west
FROM loc
GROUP BY loc_id
) box
JOIN ( SELECT #ptLat ptLat, #ptLon, ptLon ) pt
ON ptLat <= north
AND ptLat >= south
AND ptLon <= east
AHD ptLon >= west
This gets you a result set with the loc_id values matching your candidate point.
If your lat,lng data is messy--if it has lots of outlier points--this won't work very well. It's sensitive to errors. For example, if a location in Iceland has lots of points right near it, but one point in Greenland miscoded, the bounding box will be absurdly large.
If it isn't accurate enough for you, you should research convex hull algorithms. But that will take you outside pure SQL, most likely.
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?
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.
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.
Does the viewports in the Google geocoding represents the boundary boxes of the location ? Iam trying to use google viewports of particular city or location to search for the latitude and longitude values that fall in those bounding values.
I have two tables called tblproperty and tblemailalerts, tblproperty has got latitude and longitude values and tblemailalerts also got viewport + latitude and longitude values . Now I want to get the sql to get the matching records with accuracy
I want to achieve similar to zoopla search
for example when user selects location as london , properties should be shown within the boundaries of london. If they select london within 1/4 mile radius i should get the properties within the london + properties with 1/4 radius
The viewport bounds parameter only biases the results. It's not a hard limit. You can read about viewport biasing in the API documentation.
However, the viewport returned by Google for a query for "London" does represent a bounding box you can use in your SQL query.
You could also use the OpenStreetMap API. The query to get a bounding box for London is:
http://nominatim.openstreetmap.org/search?q=London&format=json
In there you will find a number of bounding boxes for places called "London" around the world, but the first one is London, United Kingdom.
I have a MySQL table with cities, and for each city I have the geo coordinates. I want to build a query that determines the nearest city given coordinates of any random position. Can anyone give me an example?
Maybe I misunderstood the question, but if you have:
[X1,Y1] - the coordinates of your position
[Xn,Yn] - for each city
Then why not just calculate the distance using the simple sqrt((X1-Xn)^2 + (Y1-Yn)^2) formula?
You could optimize it further be making some clever selects, to only get the vicinity of the position from the DB and then run the distance measuring on these cities.
http://www.davidus.sk/web/main/index/article_id/8
There you go, distance is actually a radius. It will return all cities within it.
What should be the sspn value for 1mile X 1mile square on map for google local search api?
I tried out sspn value to be 0.01,0.01 but not very sure about this.
I need to search from google local search for businesses within 1 mile radius of the current user's position.
The latitude part of the sspn is 0.0145.
The longitude part varies depending on where you are. The closer to the pole you are, the fewer miles there are per degree. If you're on the equator, then it's 0.0145, the same as the latitude, but as you move towards the poles it gets larger in proportion to 1/(cos(latitude))
The equation is 180/(3959*cos(latitude)*pi) per mile.
However, since you only need the sspn values accurate to within a factor of 2, the values 0.015,0.025 would be sufficiently accurate for much of the Earth.