lovewhoilove 小猿猴GISer 2022-07-23 09:33 發(fā)表于山東
溫馨提示:閱讀本文大約需要 18 分鐘。
OGR 屬性過(guò)濾,是利用 layer.SetAttributeFilter(filter_string) 函數(shù)進(jìn)行要素篩選的。其參數(shù) filter_string 即過(guò)濾條件,而這里依據(jù)運(yùn)算符類型將過(guò)濾條件分為了 4 類:比較運(yùn)算符(Comparison Operators)、邏輯運(yùn)算符(Logical Operators)、成員運(yùn)算符(Membership Operators)以及模糊匹配(涉及通配符)。
filter_str = "Population < 50000"
filter_str = "class != 3"
# 字符串類型的值需要加引號(hào)
filter_str = "Name = 'China'"
name = 'China'
filter_str = "Name = '{}'".format(name)
filter_str = '(Population > 25000) AND (Population < 50000)'
filter_str = "(Population > 25000) OR (Name = 'China')"
filter_str = 'Name NOT NULL'
filter_str = "(Population > 25000) OR NOT (Name = 'China')"
filter_str = 'Population BETWEEN 25000 AND 50000'
filter_str = "Name IN ('China', 'America', 'Japan')"
countries = ['China', 'America', 'Japan']
# 多個(gè)值則需要傳入一個(gè)元組,因此需要做類型轉(zhuǎn)換
filter_str = "Name IN {}".format(tuple(countries))
filter_str = "Name LIKE '_hin%'"
import sys
from osgeo import ogr
# 打開數(shù)據(jù)源:參數(shù)為1時(shí)可寫,以便創(chuàng)建新的圖層及并將屬性信息寫入
ds = ogr.Open('osgeopy-data/global', 1)
if ds is None:
sys.exit('Could not open folder.')
# 獲取輸入圖層
in_lyr = ds.GetLayer('ne_50m_populated_places')
# 屬性過(guò)濾
in_lyr.SetAttributeFilter("FEATURECLA = 'Admin-0 capital'")
# 判斷輸出圖層是否存在,若存在則刪除
if ds.GetLayer('capital_cities'):
ds.DeleteLayer('capital_cities')
# 將過(guò)濾后的圖層復(fù)制到新的數(shù)據(jù)文件中
out_lyr = ds.CopyLayer(in_lyr, 'capital_cities')
del ds # 關(guān)閉文件,將編輯后的結(jié)果寫入至磁盤文件中
def get_attr_filter_lyr(ds, in_lyr, out_lyr, filter_cond, clear=True):
"""
獲取過(guò)濾后的圖層
:param ds: 數(shù)據(jù)源對(duì)象
:param in_lyr: 輸入圖層
:param out_lyr: 過(guò)濾后的圖層名稱
:param filter_cond: 屬性過(guò)濾條件
:param clear: 是否清除屬性過(guò)濾
:return: 過(guò)濾后的圖層
"""
if clear:
in_lyr.SetAttributeFilter(None)
in_lyr.SetAttributeFilter(filter_cond)
filter_lyr = ds.CopyLayer(in_lyr, out_lyr)
ds.SyncToDisk()
if clear:
in_lyr.SetAttributeFilter(None)
return filter_lyr
filter_feat = filter_lyr.GetNextFeature()
filter_geom = filter_feat.geometry().Clone()
be_filtered_lyr.SetSpatialFilter(filter_geom)
ext = filter_lyr.GetExtent()
be_filtered_lyr.SetSpatialFilterRect(ext[0], ext[2], ext[1], ext[3])
注意:對(duì)于出錯(cuò)的語(yǔ)句或篩選后沒(méi)有結(jié)果集的語(yǔ)句,SQL 查詢的結(jié)果為空。
返回值:包含查詢結(jié)果的 OGRLayer。
import sys
from osgeo import ogr
ds = ogr.Open('osgeopy-data/global', 1)
if ds is None:
sys.exit('Could not open folder.')
sql = """SELECT * FROM ne_50m_populated_places
WHERE FEATURECLA ='Admin-0 capital'"""
lyr = ds.ExecuteSQL(sql)
if ds.GetLayer('capital_cities'):
ds.DeleteLayer('capital_cities')
out_lyr = ds.CopyLayer(lyr, 'capital_cities')
上述代碼中,使用 *(星號(hào))來(lái)表示選取所有字段,這里也可以指定需要的字段,接下來(lái)我們將總結(jié)一下 SQL 語(yǔ)句的相關(guān)語(yǔ)法。
SELECT 語(yǔ)句用于從表中選取數(shù)據(jù),其后跟表中的字段名(列名稱),多個(gè)名稱之間用 ,(逗號(hào))相連。
SELECT 字段名 FROM 表名
# 多個(gè)字段
SELECT 字段1,字段2 FROM 表名
1. 選擇所有字段
可以使用 *(星號(hào))來(lái)代表所有字段:當(dāng)然不包括下面的特定字段。
SELECT * FROM 數(shù)據(jù)表名稱
2. 選擇內(nèi)置的特殊字段
字段名稱 | 返回結(jié)果 |
---|---|
FID | 要素的 ID 值 |
OGR_GEOMETRY | OGR 幾何類型常量(如 wkbPoint) |
OGR_GEOM_WKT | 文本格式的要素幾何類型 |
OGR_GEOM_AREA | 要素的面積 |
OGR_STYLE | 要素的符號(hào)樣式的字符串 |
這里針對(duì)上表中的字段列舉幾個(gè)官網(wǎng)上的例子:
# FID
SELECT FID, * FROM nation
# 幾何類型
SELECT OGR_GEOMETRY FROM nation
# 幾何類型篩選
SELECT * FROM nation WHERE OGR_GEOMETRY='POINT' OR OGR_GEOMETRY='POLYGON'
# WKT
SELECT OGR_GEOM_WKT, * FROM nation
# WKT-篩選
SELECT * FROM nation WHERE OGR_GEOM_WKT
LIKE 'POINT%' OR OGR_GEOM_WKT LIKE 'POLYGON%'
# 面積
SELECT OGR_GEOM_AREA, * FROM nation
# 面積篩選
SELECT * FROM nation WHERE OGR_GEOM_AREA > 10000000
# 樣式
SELECT * FROM nation WHERE OGR_STYLE LIKE 'LABEL%'
3. 使用字段別名
若字段名比較長(zhǎng),我們可以使用 AS 關(guān)鍵字 來(lái)重命名一個(gè)簡(jiǎn)潔一點(diǎn)的名字:
SELECT 字段名 AS 別名 FROM 表名
4. 更改字段類型
OGR SQL 支持使用 CAST 運(yùn)算符 更改字段的類型,這里給一個(gè)官方的例子:
SELECT *, CAST(OGR_STYLE AS character(255)) FROM rivers
boolean
character(field_length).默認(rèn)長(zhǎng)度為1
float(field_length)
numeric(field_length, field_precision)
smallint(field_length) : 16 位有符號(hào)整數(shù)
integer(field_length)
bigint(field_length), 64 位整數(shù)
date(field_length)
time(field_length)
timestamp(field_length)
geometry, geometry(geometry_type), geometry(geometry_type,epsg_code)
5. DISTINCT 關(guān)鍵字
DISTINCT關(guān)鍵字 用于返回字段中唯一不同的屬性值,即去重。
SELECT DISTINCT 字段名 FROM 表名
6. 匯總運(yùn)算符(summarization operators)
還可以借助函數(shù)來(lái)處理返回的字段的屬性值,如:COUNT(實(shí)例計(jì)數(shù))、AVG(數(shù)值平均)、SUM(數(shù)值和)、MIN(數(shù)值最小值) 和 MAX(數(shù)值最大值)。
注:MIN() 和 MAX() 函數(shù)也可用于文本類型,返回按字母順序排列的最高或最低值。
SELECT MIN(prop_val), MAX(prop_val), AVG(prop_val), SUM(prop_val), COUNT(prop_val) FROM 表名
DISTINCT 關(guān)鍵字也可以和 COUNT() 結(jié)合使用:
SELECT COUNT(DISTINCT 字段名) FROM 表名
7. 函數(shù)
這里舉倆例子:個(gè)人覺(jué)得應(yīng)該用不上,最起碼用的不多。
# 拼接字符串
SELECT CONCAT(str1, st2, ...) FROM 表名
# 從字符串中提取子字符串
SELECT SUBSTR(string_expr, start_offset [, length]) FROM 表名
WHERE 子句:有條件地從表中選取數(shù)據(jù),語(yǔ)法如下:
SELECT 字段名 FROM 表名 WHERE 條件
我們?cè)O(shè)置條件會(huì)用到屬性查詢中的運(yùn)算符,具體可以參考第一小節(jié)的屬性過(guò)濾中的講解,這里列舉幾個(gè)官網(wǎng)上的例子:
SELECT * FROM 表名 WHERE (prop_val >= 100000) AND (prop_val < 200000)
SELECT * FROM 表名 WHERE NOT (area_code LIKE 'N0N%')
SELECT * FROM 表名 WHERE (prop_val IS NOT NULL) AND (prop_val < 100000)
ORDER BY 語(yǔ)句:根據(jù)指定的字段(列)進(jìn)行排序,默認(rèn)為升序排列,若要降序則加上 DESC 關(guān)鍵字(升序?yàn)殛P(guān)鍵字為 ASC)。
SELECT 字段名 FROM 表名 ORDER BY 字段名
# 降序
SELECT 字段名 FROM 表名 ORDER BY 字段名 DESC
LIMIT 子句:用于限制返回的記錄數(shù);而 OFFSET 子句:表示偏移值,用于跳過(guò)的記錄數(shù),例子如下:
SELECT * FROM 表名 LIMIT 5
SELECT * FROM 表名 OFFSET 3
SELECT * FROM 表名 LIMIT 5 OFFSET 3
OGR SQL 標(biāo)準(zhǔn)支持有限形式的一對(duì)一連接,原理:根據(jù)次表與查詢的主表之間的共享鍵,以查找次表中的記錄。
注:LEFT JOIN: 從左表(主表)返回所有的行,即使在右表(次表)中沒(méi)有匹配的行。
ds = ogr.Open('osgeopy-data/global', 1)
if ds is None:
sys.exit('Could not open folder.')
sql = """SELECT pp.name AS city, pp.pop_min AS city_pop,
c.name AS country, c.pop_est AS country_pop
FROM ne_50m_populated_places pp
LEFT JOIN ne_50m_admin_0_countries c
ON pp.adm0_a3 = c.adm0_a3
WHERE pp.adm0cap = 1"""
lyr = ds.ExecuteSQL(sql)
if ds.GetLayer('city_country'):
ds.DeleteLayer('city_country')
out_lyr = ds.CopyLayer(lyr, 'city_country')
最后做一下總結(jié),SELECT 語(yǔ)句語(yǔ)法如下:
SELECT [fields] FROM layer_name [JOIN ...] [WHERE ...] [ORDER BY ...] [LIMIT ...] [OFFSET ...]
另外,更多關(guān)于 OGR SQL 的內(nèi)容請(qǐng)參考文末第 3 篇參考資料,若覺(jué)得中文翻譯得不夠準(zhǔn)確,可以結(jié)合文末第 2 篇英文原版參考資料,關(guān)于通用的 SQL 語(yǔ)法請(qǐng)參考文末最后一篇參考資料。
參考資料:
Mingxi Zhang. Python地理數(shù)據(jù)處理[M]. 2017.
https://gdal.org/user/ogr_sql_dialect.html
https://www.osgeo.cn/gdal/user/ogr_sql_dialect.html
https://www.osgeo.cn/gdal/api/gdaldataset_cpp.html
https://www.w3school.com.cn/sql/index.asp
確定