spatial LBS GEO;
随着近几年各类移动终端的迅速普及,在手机移动定位app中,附近的人,附近的地点功能十分常见,基于地理位置的服务(LBS)和相关应用也越来越多,而支撑这些应用的最基础技术之一,就是基于地理位置信息的处理。
st_distance 函数
st_distance 函数是从mysql5.6.1才加入的。
SET @g1 = POINT(1,1), @g2 = POINT(2,2);
select st_distance (@g1, @g2);
#输出结果:1.4142135623730951
SELECT st_distance (point (1, 1),point(2,2) ) * 111195
//输出结果:157253.47706807632 单位:米
st_distance 计算的结果单位是度,需要乘111195(地球半径6371000*PI/180)是将值转化为米。
当然你也可以自定义距离函数:
CREATE FUNCTION slc (
lat1 DOUBLE,
lon1 DOUBLE,
lat2 DOUBLE,
lon2 DOUBLE
) RETURNS DOUBLE RETURN 6371 * acos(
cos(radians(lat1)) * cos(radians(lat2)) * cos(
radians(lon2) - radians(lon1)
) + sin(radians(lat1)) * sin(radians(lat2))
);
SELECT slc(1,1,2,2) from DUAL
//输出结果:157.22543203804852 km
应用场景:
假设我当时的坐标:117.069,35.86 需要查询我附近50KM内服务区,并按照距离由近及远排列
SELECT
s.id,s.name,s.lng,s.lat,
(st_distance (point (lng, lat),point(117.069,35.86) ) *111195) AS distance
FROM
road_servicearea s
HAVING distance<50
ORDER BY distance
---
另一种写法(
2核2G虚拟机上,
100万条记录
查找2公里内,结果57条数据,3ms
20公里内,结果4000条数据,36ms
):
1、先简历一张表:(MySQL 5.0 以上 仅支持 MyISAM 引擎)
CREATE TABLE address ( address CHAR(80) NOT NULL, address_loc POINT NOT NULL, PRIMARY KEY(address) );
空间索引:
ALTER TABLE address ADD SPATIAL INDEX(address_loc);
插入数据:(注:此处Point(纬度,经度) 标准写法)
INSERT INTO address VALUES('Foobar street 12', GeomFromText('POINT(30.620076 104.067221)')); INSERT INTO address VALUES('Foobar street 13', GeomFromText('POINT(31.720076 105.167221)'));
-- 查找 (30.620076,104.067221 ) 附近2公里内的地址
SELECT *,st_distance (address_loc, Point
(
30.620076 ,
104.067221
) )* 111195 as dis -- st_distance 计算的结果单位是度,需要乘111195(地球半径6371000*PI/180)是将值转化为米。
FROM address
WHERE MBRContains
(
LineString
(
Point
(
30.620076 + 2 / ( 111.1 / COS(RADIANS(104.067221))),
104.067221 + 2 / 111.1
),
Point
(
30.620076 - 2 / ( 111.1 / COS(RADIANS(104.067221))),
104.067221 - 2 / 111.1
)
),
address_loc
)
-- order by dis -- limit 10 -- 根据需要排序,或者限制结果集数量
"GEORADIUS", "GeoKey","13.1","38.1","200","km","WITHDIST"
知识科普:
地球是在不停地绕地轴旋转,在地球中腰画一个与地轴垂直的大圆圈,使圈上的每一点都和南北两极的距离相等,这个圆圈就叫作“赤道”。在赤道的南北两边,画出许多和赤道平行的圆圈,就是“纬圈”;构成这些圆圈的线段,叫做纬线。我们把赤道定为纬度零度,向南向北各为90度,在赤道以南的叫南纬,在赤道以北的叫北纬。北极就是北纬90度,南极就是南纬90度。纬度的高低也标志着气候的冷热,如赤道和低纬度地地区无冬,两极和高纬度地区无夏,中纬度地区四季分明。
从北极点到南极点,可以画出许多南北方向的与地球赤道垂直的大圆圈,这叫作“经圈”;构成这些圆圈的线段,就叫经线。公元1884平面坐标图年,国际上规定以通过英国伦敦近郊的格林尼治天文台的经线作为计算经度的起点,即经度零度零分零秒,也称“本初子午线”。在它东面的为东经,共180度;
在它西面的为西经,共180度。因为地球是圆的,所以东经180度和西经180度的经线是同一条经线。各国公定180度经线为“国际日期变更线”。为了避免同一地区使用两个不同的日期,国际日期变线在遇陆地时略有偏离。每一经度和纬度还可以再细分为60分,每一分再分为60秒以及秒的小数。利用经纬线,我们就可以确定地球上每一个地方的具体位置,并且把它在地图或地球仪上表示出来。