Ruby+PostgreSQL查询触发PG::NumericValueOutOfRange错误求助
问题解决思路
首先,这个错误不是因为numeric和double类型不统一,核心原因是acos()函数的输入超出了它的合法范围[-1, 1]。
PostgreSQL的acos()函数要求输入值必须严格在[-1,1]之间,但经纬度计算时,由于浮点(numeric/double)的精度误差,当两点距离极近或者完全重合时,你的公式计算结果可能会出现类似1.0000000001或者-1.0000000001的情况——数据量越大,碰到这种边缘情况的概率越高,就触发了NumericValueOutOfRange错误。
修复方案
直接用PostgreSQL的clamp()函数把acos()的输入值强制限制在[-1,1]范围内,修改你的查询条件:
user.left_outer_joins(:coverage_radius).where(id: i).where( '3959 * acos( clamp( cos(radians(?)) * cos(radians(coverage_radius.latitude)) * cos(radians(?) - radians(coverage_radius.longitude)) + sin(radians(?)) * sin(radians(coverage_radius.latitude)), -1.0, 1.0 ) ) <= coverage_radius.miles', job.latitude, job.longitude, job.latitude ).count
关于类型统一的问题
统一成double或numeric不是解决当前错误的必要操作,但如果你的coverage_radius.latitude/longitude和传入的job.latitude/longitude类型混合(比如一个是numeric一个是double),统一为double precision会更适合经纬度这类浮点计算——double的精度足够,计算效率也比numeric高一点。但这只是优化,不是当前错误的核心解决方案。
内容的提问来源于stack exchange,提问作者Leonardo Furtado
相关产品推荐
相关产品推荐

