MySQL 创建函数-计算经纬度距离
最近很多新手在实现周边产品或商家没有思路,今天刚好有空,给大空总结一下,在MySQL中如何实现。如有问题可以QQ(610039018)
一、准备
1.1 现有表结构
mysql> desc t_product;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(200) | NO | | NULL | |
| cover | varchar(200) | YES | | NULL | |
| price | float | YES | | NULL | |
| summary | text | YES | | NULL | |
| category_id | int(11) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
1.2 增加字段
两个字段: 纬度lat 和 经度lng
mysql> alter table t_product add lat float comment '纬度';
mysql> alter table t_product add lng float comment '经度';
创建成功后的表结构
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| title | varchar(200) | NO | | NULL | |
| cover | varchar(200) | YES | | NULL | |
| price | float | YES | | NULL | |
| summary | text | YES | | NULL | |
| category_id | int(11) | YES | | NULL | |
| lat | float | YES | | NULL | |
| lng | float | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
二、实现功能
2.1 定义函数
在mysql客户端执行如下脚本:
DELIMITER &&
CREATE FUNCTION `distance` (lat1 FLOAT, lon1 FLOAT, lat2 FLOAT, lon2 FLOAT)
RETURNS FLOAT
DETERMINISTIC
BEGIN
RETURN ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN((lat1 * PI() / 180 - lat2 * PI() / 180) / 2), 2)+ COS(lat1 * PI() / 180) * COS(lat2 * PI() / 180)* POW(SIN(( lon1 * PI() / 180 - lon2 * PI() / 180 ) / 2),2))), 2);
END &&
DELIMITER ;
注意,数值单位是 km,并保留2位小数点。
如果是MySQL5.7 版本,函数名建议不使用distance,内部可能已存在,可以改成dis。
2.2 增加测试数据
主要针对t_product表中增加测试数据。
update t_product set lng=108.952573, lat=34.335287 where id=1;
update t_product set lng=108.952573, lat=34.32539 where id=2;
增加之后的数据如下:
mysql> select * from t_product;
+----+------------------+-------+-------+---------+-------------+---------+---------+
| id | title | cover | price | summary | category_id | lat | lng |
+----+------------------+-------+-------+---------+-------------+---------+---------+
| 1 | 世纪金花-高级皮衣 | NULL | 2000 | NULL | 6 | 34.3353 | 108.953 |
| 2 | 经发大厦-办公文具 | NULL | 2880 | NULL | 7 | 34.3254 | 108.953 |
+----+------------------+-------+-------+---------+-------------+---------+---------+
以上是通过百度地图经纬度拾取工具查到的经纬度信息。可以打开http://api.map.baidu.com/lbsapi/getpoint/index.html 网站, 并在搜索框中输入"西安",点击【百度一下】按钮将地图信息转到西安市,再适当地缩放地图,将地图放大的合适的比例,最后随着鼠标的移动,会在"当前坐标点如下"的下面文本框中获取。
2.3 查询距离
以"陕西交通职业技术学院"的经续度108.946681,34.330636 查询
select title,price, distance(lat, lng, 34.330636,108.946681) as dis
from t_product
order by dis;
查询结果:
mysql> select title,price, distance(lat, lng, 34.330636,108.946681) as dis
-> from t_product
-> order by dis;
+------------------+-------+------+
| title | price | dis |
+------------------+-------+------+
| 世纪金花-高级皮衣 | 2000 | 0.75 |
| 经发大厦-办公文具 | 2880 | 0.8 |
+------------------+-------+------+