Ok I have a database with about 1800 rows, each has a column lat
and long
, what I am trying to do, it query against Google Maps V3 .getBounds
We can find result between Maps.getBounds northEast and southWest latitude and northEast and southWest longitude using below query.
Search query should be between northEast.latitude AND southWest.latitude AND northEast.longitude AND southWest.longitude
$nelat=$_GET['nelat']-0.5;
$nelng=$_GET['nelng']-0.5;
$swlat=$_GET['swlat']-0.5;
$swlng=$_GET['swlng']-0.5;
$sql ="SELECT * FROM tablename where (CASE WHEN ".$nelat." < ".$swlat."
THEN s.latitude BETWEEN ".$nelat." AND ".$swlat."
ELSE s.latitude BETWEEN ".$swlat." AND ".$nelat."
END)
AND
(CASE WHEN ".$nelng." < ".$swlng."
THEN s.longitude BETWEEN ".$nelng." AND ".$swlng."
ELSE s.longitude BETWEEN ".$swlng." AND ".$nelng."
END)";
I'm not sure the above statement is correct. Firstly, I believe the corners are nelat, nelng, swlat, swlng not as stated above "swlat, swlng, nwlat, nwlng". Secondly I believe the nelat is always going to be higher than the swlat of the window (unless the window covers one of the geographic poles which I'm not sure is even possible with google maps).
Finally, if the window covers the international date line (approx +/-180lng) i.e d < b then surely it should be "NOT BETWEEN b AND d". Perhaps someone with more specialist knowledge could confirm?
This works for me:
$condition1 = $a < $c ? "lat > $a AND lat < $c" : "lat > $a OR lat < $c";
$condition2 = $b < $d ? "lon > $b AND lon < $d" : "lon > $d OR lon < $b";
$q = "SELECT * FROM tilistings WHERE ( $condition1 ) AND ( $condition2 )";
if from Google: ( (a, b), (c, d) )
SELECT * FROM tilistings WHERE lat > a AND lat < c AND lng > b AND lng < d
All previous answers only work for 1/4 of the world!
W3t Tr3y's answer was close, but it had an error (extra "<").
All of them only work for USA, because it's in the NORTH hemisphere. They don't work for the south hemisphere, nor eastern countries (right of greenwich).
Here's a simple solution without functions or complicated stuff.
letters are the results in the order you get them from map.getBounds() i.e. swlat, swlng, nelat, nelng = a, b, c, d.
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)
or another solution with and/or (you can test it for speed, I don't know how to run it more than once in WorkBench)
SELECT * FROM tilistings WHERE
(a < c AND lat BETWEEN a AND c) OR (c < a AND lat BETWEEN c AND a)
AND
(b < d AND lng BETWEEN b AND d) OR (d < b AND lng BETWEEN d AND b)
Now you can map the whole world :) I hope someone can mark the above answers as incorrect, because they are making us lose a lot of time to millions of learning people like me. I wonder how they get so many votes when they actually dont work!
PS: The chances of of your map pixel edge matching the exact 15 decimals value of the coordinates is zillions of times less than the chances of missing a whole 3/4 of the world!
Take a look at the new spatial data and functions available in MySQL 5.7, now also for InnoDB.
Using the examples above, it takes about 1s for a table with 1 mio records to get the locations within a certain bounding box.
With ST_Within() and ST_MakeEnvelope() and the correct spatial index I get the result in less the 0.01s.