MySQL计算列应用:如何筛选距用户位置≤50km的表数据?
解决MySQL筛选用户50公里范围内数据的问题
嘿,这事儿好办!你只需要把球面距离的计算逻辑直接加到MySQL的WHERE条件里就行,用你熟悉的Active Record语法就能实现。我给你写好补充的代码,顺便解释下细节:
完整的过滤逻辑代码
$currentLatitude = 10.999; $currentLongitude = 23.354; $maxDistance = 50; // 最大距离(公里) $this->db->select('latitude, longitude'); $this->db->from('table'); // 核心:添加距离过滤条件(使用Haversine公式计算球面距离) $this->db->where("(6371 * acos(cos(radians(?)) * cos(radians(latitude)) * cos(radians(longitude) - radians(?)) + sin(radians(?)) * sin(radians(latitude)))) <= ?", [ $currentLatitude, $currentLongitude, $currentLatitude, $maxDistance ]); // 执行查询 $result = $this->db->get()->result();
关键细节说明
6371是地球的平均半径(单位:公里),如果需要用英里计算,替换成3956即可;- 用参数绑定(
?占位符)传递变量,能有效避免SQL注入风险,这是开发中的最佳实践; - 括号内的是Haversine公式的MySQL实现,专门用于计算两个经纬度点之间的球面直线距离,结果直接和50公里阈值比较。
大表查询优化建议
如果你的表数据量很大,直接计算所有行的距离会比较慢,可以先做一层粗略范围过滤,缩小计算范围后再算精确距离:
// 先筛选纬度/经度的粗略范围(±0.45度约等于50公里左右的范围) $this->db->where('latitude BETWEEN ? AND ?', [$currentLatitude - 0.45, $currentLatitude + 0.45]); $this->db->where('longitude BETWEEN ? AND ?', [$currentLongitude - 0.45, $currentLongitude + 0.45]); // 再添加精确距离过滤 $this->db->where("(6371 * acos(cos(radians(?)) * cos(radians(latitude)) * cos(radians(longitude) - radians(?)) + sin(radians(?)) * sin(radians(latitude)))) <= ?", [ $currentLatitude, $currentLongitude, $currentLatitude, $maxDistance ]);
如果你已经有自己的距离计算方法,直接替换WHERE条件里的距离计算部分即可,只要保证最终结果是公里数,且和$maxDistance比较就行。
内容的提问来源于stack exchange,提问作者dkum
相关产品推荐
相关产品推荐

