I am trying to get the nearest location to a users input from within a database, (nearest store based on latitude and longitude), so based on the users postcode I am converting that to latitude and longitude and from these results I need to search my database to find the store that is the nearest to these values. I have the latitude and longitude of all stores saved and so far (from looking at previous questions) I have tried something like:
SELECT *
FROM mystore_table
WHERE `latitude` >=(51.5263472 * .9) AND `longitude` <=(-0.3830181 * 1.1)
ORDER BY abs(latitude - 51.5263472 AND longitude - -0.3830181) limit 1;
When I run this query, it does display a result, but it is not the nearest store, not sure if it could be something to do with the negative numbers, both my columns latitude + longitude are saved as decimal data types?
You have a logic operation in the order by rather than an arithmetic one. Try this:
SELECT *
FROM mystore_table
WHERE `latitude` >=(51.5263472 * .9) AND `longitude` <=(-0.3830181 * 1.1)
ORDER BY abs(latitude - 51.5263472) + abs(longitude - -0.3830181)
limit 1;
The AND in your original version would be producing a boolean value, either 0 or 1 -- and it would only be 1 when the values match exactly to the last decimal point. Not very interesting.
There are many reasons why this is not the nearest distance, but it might be close enough for your purposes. Here are some reasons:
Euclidean distance would take the square of the differences
Distance between two latitudes depends on the longitude (varying from about 70 miles on the equator to 0 at the poles).
Related
I am trying to find the closest addresses to each other in my database. I can easily find the closest addresses to a specific coordinate ie -1.1337599754333496, 53.52299880981445 ...
SELECT st_distance_sphere(
address.coordinates,
POINT(-1.1337599754333496, 53.52299880981445 )
) AS distance
FROM address
ORDER BY distance ASC;
Is there a way to order the entire database by distance or extract a subset of the X nearest neighbours ? After wracking my brains all day I am starting to think that there isn't :-(
I have the following MYSQL query which is running on a table with around 50,000 records. The query is returning records within a 20 mile radius and i'm using a bounding box in the where clause to narrow down the records. The query is sorted by distance and limited to 10 records as it will be used on a paginated page.
The query is currently taking 0.0210 seconds to complete on average, but because the website is so busy I am looking for ways to improve this.
The adverts table has around 20 columns in it and has an index on the longitude and latitude columns.
Can anyone see anyway to improve the performance of this query? I was thinking about creating a separate table which just has the advert_id and longitude and latitude fields, but was wondering if anyone had any other suggestions or ways to improve the query below?
SELECT adverts.advert_id,
round( sqrt( ( ( (adverts.latitude - '52.536320') *
(adverts.latitude - '52.536320') ) * 69.1 * 69.1 ) +
( (adverts.longitude - '-2.063380') *
(adverts. longitude - '-2.063380') * 53 * 53 ) ),
1 ) as distance FROM adverts
WHERE (adverts.latitude BETWEEN 52.2471737281 AND 52.8254662719)
AND (adverts.longitude BETWEEN -2.53875093307 AND -1.58800906693)
having (distance <= 20)
ORDER BY distance ASC
LIMIT 10
You have to use spatial data formats and spatial indexes: how to use them.
In particular, you have to use the POINT data format to store both latitude and longitude in a single column, then you add a spatial index to that column.
The spatial index is usually implemented as an R-tree (or derivations) so that the cost of searching all points in a given area is logarithmic.
I have a MySQL query:
UPDATE
`location` `l1`
SET
`l1`.`city_id` = (
SELECT
`c1`.`id`
FROM
`city` `c1`
ORDER BY
ST_Distance_Sphere(`c1`.`coordinates`, `l1`.`coordinates`) ASC
LIMIT
1
)
that produces an error:
Incorrect arguments to st_distance_sphere
when executed against a subset of the dataset.
How do I get the value thats causing st_distance_sphere to fail?
Argument of the point class is out of the range. Besides, the sequence of arguments are longitude and latitude which is different from the usual. The following is from mysql 5.7 official reference.
https://dev.mysql.com/doc/refman/5.7/en/spatial-convenience-functions.html
The geometry arguments should consist of points that specify
(longitude, latitude) coordinate values:
Longitude and latitude are the first and second coordinates of the
point, respectively.
Both coordinates are in degrees.
Longitude values must be in the range (-180, 180]. Positive values are
east of the prime meridian.
Latitude values must be in the range [-90, 90]. Positive values are
north of the equator.
You will get this error when either latitude or longitude value is out of range. Therefore, check for ABS(long) > 180 OR ABS(lat) > 90, e.g.
SELECT
*
FROM
`location`
WHERE
ABS(ST_X(`coordinates`)) > 180 OR
ABS(ST_Y(`coordinates`)) > 90
In my case, an entry had POINT value POINT(-0.006014 99.99999999000001), i.e. the latitude value was out of range.
I'm trying to execute this query:
SELECT `venues` . *
FROM `venues`
WHERE `lat` >= 39.847991180331
AND `lng` >= -86.332592054637
AND `lat` <= 40.137846252794
AND `lng` <= -85.954901904578
LIMIT 0 , 30
Here is the table structure of the lat and lng fields and a sample row, it should be returning AT LEAST 1 row
lng decimal(65,15)
lat decimal(65,15)
Name Lng Lat
Ambre Blends Studio -86.143746979607530 39.875314973898870
However when I execure the above query it returns no rows. What's the problem here?
I'm always circumspect about floating point equality and inequality operations and MySQL has had a history of problems in the past with this sort of thing (I'm not sure which version you're using but there were some changes made around 503/505).
The first thing I would do is debug the actual statement. Start with:
select venues.* from venues
where name like 'Ambre%'
and ensure you only get one row (you may have to tweak the where clause if there's lots of rows starting with Ambre).
Then add the other subclauses one at a time until the row doesn't appear. The first would be:
select venues.* from venues
where name like 'Ambre%'
and lat >= 39.847991180331
Once you establish which condition is causing the select to fail, you can start looking into why.
I have found many similar posts and even tried to find out how to handle negative values within MySQL, but to no avail.
I have a site that I'm using Google Maps on and as a performance enhancement I'm limiting the markers that are drawn on the map to those that are within the map boundaries.
I would like to develop a query that will work with positive or negative latitude and longitude values.
For the database:
latitude FLOAT( 10, 6 )
longitude FLOAT( 10, 6 )
The query:
SELECT *
FROM `table`
WHERE `latitude` BETWEEN 47.926930 AND 47.929806
AND `longitude` BETWEEN -97.077303 AND -97.083997
If I drop the BETWEEN clause for longitude I get results, albeit incorrect with no longitude constraint.
I have tried this:
AND -`longitude` BETWEEN ABS( -97.077303 ) AND ABS( -97.083997 )
Which does work, but only for negative longitude values.
Do I need to check longitude if its negative?
You can also use the greatest() and least() functions, so you don't have to worry about the parameters. For example:
SELECT * FROM table
WHERE latitude BETWEEN least(#lat1, #lat2) AND greatest(#lat1, #lat2)
AND longitude BETWEEN least(#lon1, #lon2) AND greatest(#lon1, #lon2)
between expects the format to be somefield BETWEEN lowervalue AND highervalue. Your negative longitudes have the higher/lower values switched. It should be
AND longitude BETWEEN -97.083997 AND -97.077303
negative 97.08 is actually lower than negative 97.07
Do check how negative numbers appear on a number line. :)
SELECT *
FROM `table`
WHERE `latitude` BETWEEN 47.926930 AND 47.929806
AND `longitude` BETWEEN -97.083997 AND -97.077303