postgresql+postgis空間資料庫使用總結
阿新 • • 發佈:2019-02-06
參考資料:
pgrouting路徑導航
線上轉換shp和json格式圖形化工具
pgsql語法
pgsql幾何型別的使用
pgsql判斷點是否在面內
PostGIS的Geometry資料型別
Geometry可以說是PostGIS最重要的一個概念,是“幾何體”的意思,由於PostGIS很
好地遵守OGC的”Simple Feature for Specification for SQL”規範,目前支援的幾何體型別包含其例項有WKT格式如下:
POINT(1 1)
MULTIPOINT(1 1, 3 4, -1 3)
LINESTRING(1 1, 2 2, 3 4)
POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))
MULTIPOLYGON((0 0, 0 1, 1 1, 1 0, 0 0), (5 5, 5 6, 6 6, 6 5, 5 5))
MULTILINESTRING((1 1, 2 2, 3 4),(2 2, 3 3, 4 5))
而geometry具體表現又有兩種形式,一種叫做WKT(Well Known Text)形式,如上面的
例子。或者使用如下SQL語句瀏覽:
select AsText(pt) from test1;
另一種叫做“Canonical Form”形式,看上去是一串古怪的數字,其實是一種增強的十六
進位制編碼,使用如下SQL語句就可以瀏覽了:
select pt from test1;
EWKT、EWKB和Canonical格式
EWKT和EWKB相比OGC WKT和WKB格式主要的擴充套件有3DZ、3DM、4D座標和內嵌空間參考支援。
以下以EWKT語句定義了一些幾何物件:
POINT(0 0 0) ——3D點
SRID=32632;POINT(0 0) ——內嵌空間參考的點
POINTM(0 0 0) ——帶M值的點
POINT(0 0 0 0) ——帶M值的3D點
SRID=4326;MULTIPOINTM(0 0 0,1 2 1) ——內嵌空間參考的帶M值的多點
以下語句可以使用EWKT格式插入一個點要素到一個表中:
INSERT INTO table ( SHAPE, NAME )
VALUES ( GeomFromEWKT('SRID=4326;POINTM(116.39 39.9 10)'), '北京' )
Canonical格式是16進位制編碼的幾何物件,直接用SQL語句查詢出來的就是這種格式。
postgis3d空間語法以及函式應用:
網上關於postgis的函式有很多,這裡簡單使用幾個我用的到的函式進行測試
在執行幾何型別的sql語句的時候一定要注意型別的轉換、表空間列的屬性或者使用適當的型別,不然執行會報錯,下面的sql語句親測沒有任何問題
插入:
insert into SSS(geometryType) values(ST_GeomFromText('POINTZ(116.39 21 39.9)', 4326));
修改:
UPDATE eee SET geometryType = ST_GeomFromText('POINTM(116.39 21 39.9)',4326)
新增:
CREATE TABLE weq (id serial PRIMARY KEY, details VARCHAR(10000), template VARCHAR(255), create_time VARCHAR(255), modeUrl VARCHAR(255), geoJson
VARCHAR(255), geometryType geometry(POINTM,4326))
A是否包含B,包含返回t,不包含返回f
SELECT ST_Contains(st_astext(geometrytype),'POINTZ(151 50 30)') FROM videodata
找到 POINT(1000 1000) 100米範圍內的查詢如下:
SELECT * FROM geotable
WHERE ST_DWithin(geocolumn, ‘POINT(1000 1000)’, 100.0);
查詢點在面內,包含返回t,不包含返回f
SELECT ST_Contains(st_astext(ST_MakePolygon(ST_GeomFromText('LINESTRINGZ (0 0 1,0 2 1,2 2 1,2 0 1,0 0 1) '))),'POINTZ(1 1 5)')
或者
SELECT ST_Contains( ST_MakePolygon(ST_GeomFromText(ST_ASTEXT(geometrytype))),st_pointz(0,0,0)) FROM videodata
點是否在面內,包含返回t,不包含返回f
sql語句如下:
select * from tb_data_region_polygon0 where ST_Within(st_geomfromtext('point(114.186684 30.512029)',4326),geom);
select * from tb_data_region_polygon0 where ST_DWithin(st_geomfromtext('point(114.186684 30.512029)',4326),geom,0);
select * from tb_data_region_polygon0 where ST_Covers(geom,st_geomfromtext('point(114.186684 30.512029)',4326));
postgis 中 geomery 使用 ST_distance 計算出來的單位竟然是弧度,不是米,找了一段時間問題,發現是沒有使用投影座標引起的
於是在計算的時候,先將點變成投影座標,再來計算。
使用ST_Transform(geom, 2346)轉換之後就是以米為單位的資料了
結果以米為單位(計算長度):
SELECT ST_Length(ST_Transform(geom, 2346)) FROM ditie
這裡的2346中國西安80高絲克里投影的編號,是分帶的,使用的中央經線在南京。
加上這個,我們能正確計算出來距離,也是米。
但是如果把應用發到別的城市,比如蘇州,就會出現問題,解決方法:
查詢ditie表點到每個線的距離,條件是在80000米之內的點
select
(ST_distance(
geom::geography,
ST_GeomFromText('POINT(121 32)', 4326)::geography))
from ditie
where
ST_dwithin(geom::geography,
ST_GeomFromText('POINT(121 32)', 4326)::geography, 80000)
這樣把geometry轉成geography,轉換之後,全球都可以使用了
下面這種辦法查出來的結果也是以米為單位的兩點間的距離
SELECT ST_Distance(
ST_Transform(ST_GeomFromText('POINT(-87.734087560562 43.770129071141)',4326),26986),
ST_Transform(ST_GeomFromText('POINT(-87.747382933006 43.759234252055)', 4326),26986)
);
在專案中,我們也可以直接把座標存成 geography格式的,這樣就能避免資料轉來轉去的了:
ST_GeographyFromText('SRID=4326;POINT(-110 30)')
改變表的空間欄位srid為4326
update table_name set the_geom = st_geomfromtext(ST_AsText(the_geom),4326)