I am getting lat/lng bounds from google map in client side through xhr to my php script. which is making an sql query to search location within that bounds. My table stores lat, lng as different columns. now how can I arrange my where queries such that only the points within the specified NE, SW bounds are returned.
In database its stored as number and I don't know if there already is any postgresql specific aggregate function to do the same.
Am I missing something? It's just a rectangular bounds check. It's not like you need to calculate the distance between the points.
WHERE lat BETWEEN lat_of_corner_a AND lat_of_corner_b
AND lon BETWEEN lon_of_corner_a AND lon_of_corner_b
I posted the working solution here:
Get all records from MySQL database that are within Google Maps .getBounds?
Alex's solution only works in USA, specifically in the north hemisphere, west region (were decreasing values fit the order in which Google provides the bouds values.
This one works for the other 3/4 of the world.
SELECT * FROM tilistings WHERE
(CASE WHEN a < c
THEN lat BETWEEN a AND c
ELSE lat BETWEEN c AND a
END)
AND
(CASE WHEN b < d
THEN lng BETWEEN b AND d
ELSE lng BETWEEN d AND b
END)
(See the linked post for more details)
Related
I'm building a geolocation advertising platform and I've run into a snag. I can successfully calculate all of the businesses advertising within a given radius to a user using this (page 8). Now, the client wants to change the radiuses of the advertisers which you can think of as "service areas". A basic advertiser will have a service radius of 100 miles, but other companies who are larger or spend more on advertising might have a service area of 250 or 500 miles, for example. With this change, the previous calculation does not work.
How can I take all of these variable radiuses and distances in order to return all of the advertisers that would be valid for a visitor?
To better illustrate my problem, take a look at:
Currently we calculate and return all of the advertisers within a 100 mile radius of a user (companies A, B, and C). With the new change, we need to return all of the companies that have a service area that covers the user, which includes company D. Company E has a smaller service area/radius which doesn't cover the user, so that record should not be returned.
The advertiser's table currently looks similar to:
id
name
lat
lng
radius
Given lat/lng of two points distance in miles can be calculated, see:
Find distance between two points using latitude and longitude in mysql
So if the visitor position is given (let's define it as visitor_latitude and visitor_longitude) the query that returns all the advertisers in range is:
SELECT *,
69.0412 * DEGREES(ACOS(COS(RADIANS(lat))
* COS(RADIANS(visitor_latitude))
* COS(RADIANS(lng - visitor_longitude))
+ SIN(RADIANS(lat))
* SIN(RADIANS(visitor_latitude)))) AS distance
FROM advertisers
WHERE distance <= radius
hi i am using this map
https://google-developers.appspot.com/maps/articles/mvcfun/step6
i can get the latitude and longitude of the required location also i can get the distance (radius). so i have a database in which my each record have latitude and longitude. i want to search the record within the range selected on the map. how the sql query will work ?
for better explanation my each record have a latitude and longitude. user will select the map and i want to search the record within selected range.
The way I have always done this is to use the maps api to draw a circle with the required radius, find the lat long bounds of this circle and then query the database:
SELECT * FROM yourtable WHERE lat BETWEEN a AND c AND lng between b AND d
Where a and b are you top left coordinates and c and d are your bottom right. (more information available here).
Now that you have all objects within your bounding box you will need to pass them back to your front-end and determine whether or not they are within your radius. See this answer for more information.
I have downloaded the ordnance survey which contains the postcode eastings and northings of all UK postcodes and I would like to perform a mySQL query which calculates and shows the results of a given distance.
Firstly I need to match up all records in properties to the postcode table to show each properties easting and northing joined into the results.
I then need to calculate the distance between the given postcode and each property record and display only the ones which fall within the given distance.
I have found lots of examples for using long/lat but I cannot seem to find any good examples for using the ordance survey easting and northing system. According to the ordenance survey guide I should be getting an answer in metres for using the full 6 digits.
I am also getting this error:
errorErrormessage: BIGINT UNSIGNED value is out of range in '(((mjm.pc.Eastings - 436421) ^ 2) + ((mjm.pc.Northings - 291786) ^ 2))'
When trying to test the query:
$query = "
SELECT * , SQRT( (pc.Eastings - {$e1})^2 + (pc.Northings - {$n1})^2) AS distance
FROM properties p, postcodes pc
WHERE concat( p.POSTCODE1, p.POSTCODE2 )= pc.Postcode HAVING distance <= 10
LIMIT 0 , 30
";
Can someone help me understand what I need to do to make this work please?
^ is the XOR operator, not the square. Can you try this?
SQRT( POW(pc.Eastings - {$e1}, 2) +
POW(pc.Northings - {$n1}, 2)) as distance
Background /
Currently right now we have a 100 or so Lat/Lng wich get mapped onto google maps. The aim is to show the hot spot location of these by selecting from the database La/Lo values that are within a few meters of each other.
The group values will then be used to find the central point and draw a circle on the map of the hot spot.
Current setup /
Currently the datase we are requesting from has just id(int),La(float),Lo(float)
Concept /
What i ''think'' is needed is this
Select * from table
Group by (
( La + 0.30 && La - 0.30) && ( Lo + 0.30 && Lo - 0.30)
)
First off, the earth is not a square so to get accurate distances you will need to use a haversine function (look it up), however, for distances of a few metres , maybe accuracy doesn't matter.
Second, the distance between degrees of lattitude varies between 110.574 and 111.694 km and for degrees of longitude between 111.32 and 0.0 km (yes 0.0km at the poles). In any case 0.3 is somewhere between 0 and 35,000 m - not exactly "a few" unless your hotspots are at the north and/or south poles.
Third, ignoring the bad geography, the SQL statement you are groping for will require a cross join and sorting on calculated distances and will be very slow even for a small data set - you need to look at using whatever support mysql has for native geography types. I know SQL Server has them and I suspect MySQL does too.
Edit
It does, see this question.
This question already has answers here:
MySQL Great Circle Distance (Haversine formula)
(9 answers)
Closed 2 years ago.
Each user in my db is associated to a city (with it's longitude and latitude)
How would I go about finding out which cities are close to one another?
i.e. in England, Cambridge is fairly close to London.
So If I have a user who lives in Cambridge. Users close to them would be users living in close surrounding cities, such as London, Hertford etc.
Any ideas how I could go about this? And also, how would I define what is close? i.e. in the UK close would be much closer than if it were in the US as the US is far more spread out.
Ideas and suggestions. Also, do you know any services that provide this sort of functionality?
Thanks
If you can call an external web service, you can use the GeoNames API for locating nearby cities within some radius that you define:
http://www.geonames.org/export/web-services.html
Getting coordinates from City names is called reverse geo coding. Google maps has a nice Api fot that.
There is also the Geonames project where you get huge databases of cities, zip codes etc and their cooridnates
However if you already have the coordinates, its a simple calculation to get the distance.
The tricky thing is to get a nice performant version of it. You probably have it stored in a mysql database, so you need to do it there and fast.
It is absolutely possible. I once did a project including that code, I will fetch it and post it here.
However to speed things up I would recommend first doing a rectangular selection around the center coordinates. This is very, very fast using bee tree indexes or even better stuff like multidimensional range search. Then inside that you can then calculate the exact distances on a limited set of data.
Outside that recangular selection the directions are so vast that it does not need to be displayed or calculated so accurately. Or just display the country, continent or something like that.
I am still at the office but when i get home i can fetch the codes for you. Int he meantime it would be good if you could inform me how you store your data.
Edit: in the mean time here you have a function which looks right to me (i did it without a function in one query...)
CREATE FUNCTION `get_distance_between_geo_locations`(`lat1` FLOAT, `long1` FLOAT, `lat2` FLOAT, `long2` FLOAT)
RETURNS FLOAT
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE distance FLOAT DEFAULT -1;
DECLARE earthRadius FLOAT DEFAULT 6371.009;
-- 3958.761 --miles
-- 6371.009 --km
DECLARE axis FLOAT;
IF ((lat1 IS NOT NULL) AND (long1 IS NOT NULL) AND (lat2 IS NOT NULL) AND (long2 IS NOT NULL)) THEN -- bit of protection against bad data
SET axis = (SIN(RADIANS(lat2-lat1)/2) * SIN(RADIANS(lat2-lat1)/2) + COS(RADIANS(lat1)) * COS(RADIANS(lat2)) * SIN(RADIANS(long2-long1)/2) * SIN(RADIANS(long2-long1)/2));
SET distance = earthRadius * (2 * ATAN2(SQRT(axis), SQRT(1-axis)));
END IF;
RETURN distance;
END;
i quoted this from here: http://sebastian-bauer.ws/en/2010/12/12/geo-koordinaten-mysql-funktion-zur-berechnung-des-abstands.html
and here is another link: http://www.andrewseward.co.uk/2010/04/sql-function-to-calculate-distance.html
The simplest way to do this would be to calculate a bounding box from the latitude and longitude of the city and a distance (by converting the distance to degrees of longitude).
Once you have that box (min latitude, max latitude, min longitude, max longitude), query for other cities whose latitude and longitude are inside the bounding box. This will get you an approximate list, and should be quite fast as it will be able to use any indexes you might have on the latitude and longitude columns.
From there you can narrow the list down if desired using a real "distance between points on a sphere" function.
You need a spatial index or GIS functionality. What database are you using? MySQL and PostgreSQL both have GIS support which would allow you to find the N nearest cities using an SQL query.
Another option you might want to consider would be to put all of the cities into a spatial search tree like a kd-tree. Kd-trees efficiently support nearest-neighbor searches, as well as fast searches for all points in a given bounding box. You could then find nearby cities by searching for a few of the city's nearest neighbors, then using the distance to those neighbors to get an estimate size for a bounding box to search in.