MYSQL - 邮政编码半径 - 优化并返回到外部选择的距离

标签 mysql

我有一个关于邮政编码半径的问题。下面的选择有我发现的半径函数。还可以,但是有点慢。另外,有没有办法返回到外部选择的距离?为了简化这个问题,我已经对经度和纬度进行了硬编码。

提前致谢。 菲尔

                       SELECT 
                            A.MEMBER_ID                                                                                                                                                                                                                       
                       FROM MEMBER A,                                                                                         
                            DETAILS B,                                                                                             
                            ZIPCODE D
                      WHERE A.ZIPCODE_CODE IN (Select resultzip.ZIPCODE from                                                        
                                (SELECT                                                                                                        
                                    pos.ZIPCODE,                                                                                                 
                                    3958 * 2 * ASIN(SQRT(POWER(SIN(( 39.946438 - abs(pos.LATITUDE)) * pi() / 180 / 2),2) +           
                                    COS( 39.946438 * pi()/180) * COS(abs(pos.LATITUDE) * pi() / 180) * POWER(SIN(( -74.915955 - pos.LONGITUDE) *
                                    pi() / 180 / 2), 2) )) AS distance_return_this_to_outer_select                                                                           
                                FROM ZIPCODE pos                                                                                           
                                HAVING distance_return_this_to_outer_select < 100                                                                        
                                ORDER BY distance_return_this_to_outer_select)                                                                                             
                                AS resultzip)                                                                                                                                                                             
                            AND A.ZIPCODE_CODE = D.ZIPCODE                                                                  
                            AND A.MEMBER_ID = B.MEMBER_ID                                
                            Limit 0,15;  

最佳答案

我刚刚编写了一个距离函数,较大 UDF 的一部分在 AMD A10-6800K 2GHz 处理器上运行 150 纳秒。您可以围绕它创建一个 UDF 包装器(查看 MySQL 源代码中的 sql/udf_example.c,搜索 myfunc_double):

    #define R_EARTH_MILES 3963.1676
static inline double deg2rad(double deg) {
  return (deg * M_PI / 180);
}

static inline double rad2deg(double rad) {
  return (rad * 180 / M_PI);
}


    static inline double earth_distance(double lat1, double lon1, double lat2, double lon2)
    {
        double dlat = deg2rad(lat2 - lat1), dlon = deg2rad(lon2 - lon1);
        double central_hs =  (1.0 - cos(dlat))/2.0 + cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * (1.0 - cos(dlon))/2.0;
        double central_angle = 2 * atan2(sqrt(central_hs), sqrt(1 - central_hs));
        return R_EARTH_MILES * central_angle;
    }

它使用半正弦方法,该方法依赖于一些巧妙的三角恒等式来减少浮点运算。

更新:

将其包装到一个独立的 UDF 中,您应该能够按照 README.md 文件中的说明进行部署:

http://github.com/spachev/mysql_udf_bundle

再想一想,您的缓慢问题可能与计算性能无关,而是由于检查了太多行来回答问题,因为我们无法使用键进行过滤。

我建议使用 SPATIAL 键将坐标存储在 GEOMETRY 类型中,然后使用 CONTAINS() 函数和一个以目标点为中心、以搜索直径为边的正方形来过滤掉大部分点,然后使用地球距离法过滤掉其余的。

关于MYSQL - 邮政编码半径 - 优化并返回到外部选择的距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33558173/

相关文章:

java - JPA 复合外主键

javascript - Node.Js 使用 sequelize/body 解析器和 mysql 添加记录

php - 如何阻止 PHP 向 MYSQL 数据库添加空白行/字段

mysql - SQL 外部连接 - 执行不当

java - 如何在管理中检查数据库中的真/假值,并相应地重定向? (Web应用程序)

mysql - 按对对记录进行分组 SQL 查询

mysql - 事务中的 JDBC/MySQL 查询和更新

PHP MySQL 数据库测试

java - 在数据库和 postman 上无法看到实际上传的文件(.pdf 格式)格式?

mysql - 根据匹配值选择 A 列或 B 列