On my site I\'m trying to get locations nearby.
I\'m trying to use the Haversine formula for this.
PostgreSQL does have a radians function:
radians(dp)
degrees to radians
but radians
wants a floating point argument and you are trying to give it a string of some sort:
Undefined function: 7 ERROR: function radians(text)
[...] HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Emphasis mine. Apparently your lat
and lng
columns are char(n)
, varchar(n)
, or text
columns. You should fix the column types for lat
and lng
to be numeric
, float
, or some other floating point type; in the mean time, you can cast your strings by hand and hope that you don't have any broken data:
radians(cast(lat as double precision))
MySQL does a lot of implicit type conversions, PostgreSQL is rather more strict and requires you to say exactly what you mean.
Update for the second problem: The HAVING
clause is evaluated before the SELECT
clause so column aliases in the SELECT
are not generally available anywhere else in the query. You have a couple options, you can repeat your big ugly Haversine:
SELECT id, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) AS distance
FROM shops
HAVING ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) < 25
ORDER BY name asc
Or use a derived table to avoid repeating yourself:
select id, distance
from (
select id, name, ( 6371 * acos( cos( radians(51.8391) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(4.6265) ) + sin( radians(51.8391) ) * sin( radians( lat ) ) ) ) as distance
from shops
) as dt
where distance < 25.0
order by name asc
Conversion to radians is trivial:
radians(n) = n * PI / 180.0