Question

I am trying to run to find the closest point with a long and lat. Which works fine is i have separate value stored in my db, however i have a single piped string, which i am able to split with a substring index. However when i try and combine these functions in my select query i am not getting any joy.

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 1), '|', -1) as 'lat',
SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 2), '|', -1) as 'lng',
title,
( 6371 * acos( cos( radians(51.527351) ) * cos( radians( 'lat') ) * cos( radians( 'lng' ) - radians(0.765544) ) + sin( radians(51.527351) ) * sin( radians( 'lat' ) ) ) ) AS distance 
FROM locations HAVING distance < 500
ORDER BY distance
LIMIT 0 , 20

Can anyone shed some light?

Was it helpful?

Solution

radians( 'lat')

In this part of the query, 'lat' is a string, not a column name or similar. When passing that string to radians, it will be converted to a number, in this case to zero. So you're converting 0 to radians.

You cannot use one column as the input to the computation of the value of another column. You either have to repeat the expression, or use a subquery like this:

SELECT lat, lng, title,
  (6371 * acos(cos(radians(51.527351)) *
   cos(radians(lat)) * cos(radians(lng) - radians(0.765544)) +
   sin(radians(51.527351)) * sin(radians(lat)))
  ) AS distance
FROM
  (SELECT title,
     SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 1), '|', -1) + 0 as lat,
     SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 2), '|', -1) + 0 as lng
   FROM locations
  ) AS sub
HAVING distance < 500
ORDER BY distance
LIMIT 0 , 20

OTHER TIPS

Here was my solution which repeats the query. I haven;t had a chance to test of benchmark the differing solutions, but the subquery solution is more pleasant

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 1), '|', -1) as 'latitude',
       SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 2), '|', -1) as 'longitude',
(
  3959 * acos(
    cos(radians({MYLAT})) * cos(radians(SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 1), '|', -1)))
    * cos(radians(SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 2), '|', -1))) - radians({MYLONG}) + sin(radians({MYLAT})) 
    * sin( radians(SUBSTRING_INDEX(SUBSTRING_INDEX(longlat, '|', 1), '|', -1)))
  )
)
AS distance,
title

FROM locations
ORDER BY distance
LIMIT 0 , 20

Turns out i'm going to be using this equation everywhere now, so glad to get it nailed :)

I'm using the averaged 3959 as the earth's radius, however i wonder if i might be better to use some kind regional latitude for different global locations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top