Using the Haversine formula with PostgreSQL and PDO

后端 未结 2 474
梦如初夏
梦如初夏 2021-01-01 03:34

On my site I\'m trying to get locations nearby.

I\'m trying to use the Haversine formula for this.

  • http://en.wikipedia.org/wiki/Haversine_formula
相关标签:
2条回答
  • 2021-01-01 04:16

    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
    
    0 讨论(0)
  • 2021-01-01 04:18

    Conversion to radians is trivial:

    radians(n) = n * PI / 180.0
    
    0 讨论(0)
提交回复
热议问题