地理空間數據Geometry在MySQL中使用


建表腳本

CREATE TABLE `z_gis` ( `id` bigint(20) NOT NULL, `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '姓名', `gis` geometry NOT NULL COMMENT '空間位置信息', `geohash` varchar(20) GENERATED ALWAYS AS (st_geohash(`gis`,8)) VIRTUAL, `item_id` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `id` (`id`), SPATIAL KEY `idx_gis` (`gis`), KEY `name` (`name`), KEY `idx_geohash` (`geohash`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='空間位置信息';

此時創建了一張位置信息表,每個人對應的經緯度都會以geometry類型存在表中,geohash字段是把坐標系分成很多小方格,然后將經緯度轉化成字符串,其原理可自行百度,在這里就不多說了。

geometry類型好像不能為null,所以建表時必須為not null。

插入表數據

insert into z_gis(id,name,gis,item_id) values (880000,'張三',st_geomfromtext('point(108.9498710632 34.2588125935)'), 100), (890000,'李四',st_geomfromtext('point(108.9465236664 34.2598766768)'), 101);


1. 查詢張三的經緯度信息

#496 張三 POINT(108.9465236664 34.2598766768) select id, name, st_astext(gis) gis from z_gis where name = '張三';

注:st_astext()函數是將geometry類型轉化為字符串

2. 修改張三的位置信息

update z_gis set gis = st_geomfromtext('point(108.9465236664 34.2598766768)') where name = '張三';

 

3. 查詢張三和李四之間的距離
注:st_distance_sphere()函數是計算兩點之間距離,所以傳兩個參數,都是geometry類型的,floor()函數是把計算出的距離取整,以米為單位。

-- 計算廈門到安溪的距離,單位米
select floor(st_distance_sphere( POINT(118.03394,24.48405), -- 廈門經緯度
    POINT(118.18685,25.05544) -- 安溪經緯度
)) distance -- 查詢張三和李四之間的距離
select floor(st_distance_sphere( (select gis from z_gis where name= '張三'), gis )) distance from z_gis where name= '李四';

 

4. 查詢距離張三500米內的所有人

張三數據信息:(id, name, gis, geohash)(183    張三    POINT(120.259718 30.138463)    wtme2wd3    53) -- POINT(120.259718,30.138463) 張三的經緯度 -- wtme2w 張三的geohash值 -- 183 張三的主鍵id
select name, --推薦用經緯度傳入,不要子查詢
    -- floor(st_distance_sphere((SELECT gis FROM z_gis WHERE name = '張三'), gis)) distance, 
    floor(st_distance_sphere(point(120.259718,30.138463), gis)) distance, st_astext(gis) point from z_gis where geohash like 'wtme2w%' and st_distance_sphere(point(120.259718,30.138463), gis) < 5000 and id<>183;

前面說過geohash是把經緯度轉成字符串,建表的時候我定義讓它轉成8位字符,當兩個點離得越近時,它生成的geohash字符串前面相同的位數越多,所以我在這里先用left()截取前6位字符,前6位相同的誤差在±600米左右,然后模糊查詢,查出大概符合條件的數據,最后再精確比較,下面是geohash官方文檔對geohash長度和距離誤差的說明:

注意:用geohash 查詢會有邊界問題,所以查詢出來的結果又可能不准確,可以用程序(例如java代碼)先查出當前點周圍8個范圍的geohash值,然后再匹配這9個范圍的所有數據,這樣就解決了geohash 的邊界問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM