ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ArcGIS属性查询公式大全:数值日期文本与字段计算器避坑指南

ArcGIS属性查询公式大全:数值日期文本与字段计算器避坑指南 做数据这行久了最怕听到的一句话就是“这个字段帮我筛一下”。ArcGIS 属性查询公式看着简单无非是字段加运算符可真到了几十万条记录的图层上写错一个引号、漏掉一个空值判断结果就是差之毫厘谬以千里。这篇东西整理了我这些年在地块核查、管线排查、人口数据清洗里攒下来的一百来个 ArcGIS 属性查询公式按数值、日期、文本、几何质量、字段计算器分成几组每条都标了适用场景和容易翻车的地方。不管你是刚摸软件的学生还是天天跟地类图斑打交道的从业者都能直接抄过去改字段名就用。全文默认以文件地理数据库File Geodatabase的 SQL-92 语法为准其他数据源的差异我会在开头一次性讲清楚省得你一条条试。1. 属性查询公式的语法地基与数据源差异1.1 为什么同一条公式换个图层就报错很多人第一次被“按属性选择”坑都是因为拿着 Shapefile 的习惯去写文件地理数据库的语句。ArcGIS 里“按属性选择”实际是把表达式翻译成底层数据源的 SQL 交给它执行不同数据源的语法规则完全不一样这跟 Word 里换个字体就变样是一个道理——外壳一样内核不同。字段名的包裹符号是第一个分水岭。文件地理数据库.gdb和个人地理数据库.mdb里字段名要用双引号Shapefile 虽然也认双引号但字段名被截断成 10 个字符是常态个人地理数据库的图形界面里有时会写成方括号。字符串常量的引号则是第二个坑所有数据源都用单引号包字符串绝不是双引号。我见过太多人写NAME 北京软件直接判定为“字段 NAME 等于字段 北京”两个字段比大小能返回结果才怪。日期类型的处理差异更大这也是报错最集中的地方。文件地理数据库用DATE 2024-01-01或TIMESTAMP 2024-01-01 08:00:00Shapefile 用井号包裹#2024-01-01#个人地理数据库同样用#。同一个日期条件换数据源就得改写没有万能写法。提示动手写公式前先在图层的“属性”里看清楚数据源类型再决定用哪套语法。这一步花十秒钟能省半小时排查。1.2 空值、NULL 与空字符串的三重陷阱这是我觉得最值得单独拎出来讲的一点。在 ArcGIS 里NULL 表示“这个格子什么都没填”空字符串表示“填了但内容是空的”零0表示“填了且是数字零”。这三者在 SQL 里的行为完全不同尤其在做逻辑否定的时候。举个实际例子你要找“面积大于 1000 的地块”写成NOT AREA 1000看起来等价于AREA 1000但结果集往往少了那些 AREA 为 NULL 的记录——因为 NULL 参与任何比较都返回未知NOT 未知还是未知这些记录会被悄悄排除掉。做面积核查的时候这种“悄悄丢记录”是最危险的你以为筛完了实际漏了一批。另一个常见错误是把 NULL 当成字符串来比。NAME 在文件地理数据库里不会返回 NULL 记录NAME NULL更是只会去找名字真的叫“NULL”的要素。判断空值必须用IS NULL和IS NOT NULL这是关键词不能省。而 Shapefile 有个先天缺陷它的字段默认为空时会填 0 或空字符串几乎不产生真正的 NULL所以你拿IS NULL去查 Shapefile 常常一条都查不到这时候只能退而求其次用NAME 或NUM 0来判断。理解了这层差异后面那些公式你就能举一反三而不是死记硬背。2. 数值型与日期型字段的常用查询公式2.1 数值字段的 25 条实用公式数值字段的查询围绕比较、区间、取整、算术组合这几类展开我把日常用得最顺手的列在下面全部假设字段已加双引号字符串用单引号。-- 1. 面积大于1000 AREA 1000 -- 2. 人口在5000到50000之间闭区间 POP 5000 AND POP 50000 -- 3. 用 BETWEEN 写闭区间更简洁 AREA BETWEEN 100 AND 500 -- 4. 按对象ID精确定位单个要素 OBJECTID 100 -- 5. 排除某个ID注意NULL不受影响 OBJECTID 1 -- 6. 等级在指定几个值里 GRADE IN (1, 3, 5) -- 7. 高度区间组合 HEIGHT 20 AND HEIGHT 50 -- 8. 逻辑取反注意NULL记录会被排除 NOT AREA 1000 -- 9. 计算人口密度并筛选先确保AREA不为0 POP / AREA 500 -- 10. 属性长度与几何长度差值异常用于拓扑质检 ABS(SHAPE_Length - LENGTH) 0.01 -- 11. 取模判断奇偶MOD函数兼容性更好 MOD(OBJECTID, 2) 0 -- 12. 算术缩放比较 OBJECTID * 10 500 -- 13. 主条件叠加或条件用括号明确优先级 PRICE 100 AND (TYPE A OR TYPE B) -- 14. 两个面积字段相减找差值 AREA_1 - AREA_2 0 -- 15. 两字段求和后比较 (AREA_1 AREA_2) 100 -- 16. 四舍五入后比较 ROUND(AREA, 2) 100.55 -- 17. 文本数字转数值后比较 CAST(CODE AS INTEGER) 100 -- 18. 正数且非空 NUM 0 AND NUM IS NOT NULL -- 19. 含负数的对称区间 VALUE BETWEEN -10 AND 10 -- 20. 小于某汇总阈值的记录 AREA 666.67 -- 21. 数值达标或为空宽松筛选 LEVEL 3 OR LEVEL IS NULL -- 22. 向上取整后等于某值 CEILING(AREA) 100 -- 23. 向下取整后等于某值 FLOOR(HEIGHT) 10 -- 24. 多条件复合筛选 SCORE 60 AND SCORE 90 AND CLASS A -- 25. 坐标异常值排查 LON 0 OR LAT 0这里面第 11 条要特别说明取模运算在部分数据源里不认%符号得用MOD()函数写之前最好先用一两条测试一下。第 17 条的CAST是类型转换的救命稻草当你的编号字段被存成文本而你想按数值大小排序筛选时不转换就只能得到“1、10、100、2”这种字典序结果做编号核查时能把你气笑。第 8 条那种NOT写法我一般不建议用除非你确实想连带排除空值。做数据核查时宁可拆成两个条件写清楚先筛有效值区间再单独处理空值逻辑一目了然交出去的报告别人也看得懂。2.2 日期字段的 10 条查询公式日期查询的难点全在格式和函数支持上下面按文件地理数据库为准Shapefile 的写法我在末尾单独标注。-- 26. 某天之后 DATE DATE 2024-01-01 -- 27. 精确到秒的时间点之后 DATE TIMESTAMP 2024-01-01 08:00:00 -- 28. 整年区间 DATE BETWEEN DATE 2024-01-01 AND DATE 2024-12-31 -- 29. 按年份提取 EXTRACT(YEAR FROM DATE) 2024 -- 30. 按月份提取筛汛期 EXTRACT(MONTH FROM DATE) IN (6, 7, 8) -- 31. 日期为空的记录 DATE IS NULL -- 32. 晚于当前日期 DATE CURRENT_DATE -- 33. 早于当前时间戳 DATE CURRENT_TIMESTAMP -- 34. Shapefile 的日期写法改用井号 DATE #2024-01-01# -- 35. 文本日期转时间戳后比较 CAST(DATE_STR AS TIMESTAMP) TIMESTAMP 2024-01-01 00:00:00EXTRACT是我最常用的函数按年、月、日、时提取都可以做数据分年统计时特别顺手。但要注意它在大数据量下基本会让索引失效全表扫描跑起来很慢如果图层几十万条建议先用“字段计算器”把年份单独算成一个短整型字段再来筛选速度能快一个数量级。第 35 条那个CAST专治“日期被存成文本”的情况。这种情况多半是从 Excel 或者 CAD 导进来的日期字段类型是字符串你按日期比较它不认。转一次就好但转之前得确认文本格式规范比如全是2024-01-01这种要是混着2024/1/1和20240101转换会报错得先用字段计算器统一格式。注意个人地理数据库.mdb的日期用#2024-01-01#和 Shapefile 一样别照搬 gdb 的写法。3. 文本型字段与字符处理查询公式3.1 模糊匹配与通配符的 25 条用法文本查询是日常用得最多的尤其是地名、编号、类型名称的筛选。ArcGIS 里 LIKE 支持%匹配任意长度字符_匹配单个字符但下划线的支持因数据源而异为了稳妥我建议日常只用%。-- 36. 精确等于 NAME 北京市 -- 37. 以某字开头 NAME LIKE 北% -- 38. 以某字结尾 NAME LIKE %村 -- 39. 包含某字 NAME LIKE %河% -- 40. 单字符通配注意部分数据源不支持下划线 NAME LIKE A_% -- 41. 不以某字结尾 NAME NOT LIKE %镇 -- 42. 编码前缀匹配 CODE LIKE 1101% -- 43. 大写后匹配避免大小写不一致 UPPER(NAME) ABC -- 44. 小写后匹配 LOWER(NAME) abc -- 45. 多值匹配 TYPE IN (A, B, C) -- 46. 或条件等价写法 NAME A OR NAME B -- 47. 按字符长度筛选 CHAR_LENGTH(NAME) 10 -- 48. 姓氏开头组合 NAME LIKE 张% OR NAME LIKE 李% -- 49. 地址同时包含路和号 ADDR LIKE %路% AND ADDR LIKE %号% -- 50. 截取子串后比较 SUBSTRING(CODE, 1, 2) 11 -- 51. 非空字符串判断 REMARK -- 52. 空字符串判断 NAME -- 53. 多字段拼接后匹配 CONCAT(PROV, CITY, COUNTY) LIKE %1101% -- 54. 判断子串位置 POSITION(河 IN NAME) 0 -- 55. 去掉首尾空格后匹配 TRIM(NAME) 朝阳 -- 56. 电话号码前缀筛选 TEL LIKE 13% -- 57. 排除未知值且非空 NAME 未知 AND NAME IS NOT NULL -- 58. 定长编码匹配四个任意字符 CODE LIKE ____ -- 59. 排除特定后缀 NAME NOT LIKE %临时 -- 60. 包含数字编号的备注 REMARK LIKE %号% AND REMARK LIKE %号%第 43、44 条的大小写转换函数在文件地理数据库里可用但在 Shapefile 上支持不全跨数据源时慎用。更稳的办法是提前用字段计算器把字段统一成大写或小写查询时就不会有歧义。我以前处理一批从不同部门收来的地名数据一个写“Beijing”一个写“beijing”一个写“BEIJING”最后就是靠统一大小写才匹配上的。第 55 条的TRIM治的是“看不见的空格”。从 Excel 复制粘贴过来的文本常带首尾空格你肉眼看着是“朝阳”实际存的是“朝阳 ”用匹配死活找不到。这种情况下TRIM就是照妖镜一用一个准。同理还有字段计算器里的.strip()后面会讲。第 58 条的LIKE ____用四个下划线匹配四个任意字符适合筛固定位数的编号前提是你的数据源支持下划线通配。图省事的话也可以改用CHAR_LENGTH(CODE) 4兼容性更好。3.2 文本查询避坑的三个关键点第一ArcGIS 的属性查询不支持正则表达式。网上那些把正则塞进方括号LIKE %[0-9]%的写法在文件地理数据库里会直接报错或者匹配不到东西。想按正则筛只能把数据导出后用 Python、或者用字段计算器配合re模块处理别指望在查询对话框里一步到位。第二LIKE的前缀匹配能用上索引%xxx%这种前置通配会让索引彻底失效。几十万条的图层上NAME LIKE %河%跑起来可能要好几分钟。我的做法是先用范围缩小候选集比如叠加行政区范围再查或者把常用的“含某关键字”单独算成一个 0/1 标记字段直接查 1速度天差地别。第三中文查询里单引号、双引号的输入法一定切到英文半角。中文全角的引号在表达式里是非法字符报的错还特别含糊说“语法错误”但不告诉你错在哪很多人卡在这里最后靠重写才蒙对。写公式的时候把输入法切成英文这个习惯能省下大量时间。4. 空值异常值与几何字段的核查公式4.1 数据质量核查的 15 条公式数据清洗阶段最耗时间的不是筛“符合条件”的记录而是找“有问题”的记录。下面这些公式是我做入库检查时几乎每批数据都要跑一遍的。-- 61. 关键字段为空 FIELD IS NULL -- 62. 关键字段非空 FIELD IS NOT NULL -- 63. 空值或空字符串一次筛出所有缺失 NAME IS NULL OR NAME -- 64. 名称字段自己等于自己用于验证非空逻辑 NAME NAME -- 65. 几何长度大于0 SHAPE_Length 0 -- 66. 几何面积等于0 SHAPE_Area 0 -- 67. 面积小于1平方米的碎小面 SHAPE_Area 1 -- 68. 属性面积与几何面积偏差过大 ABS(SHAPE_Area - AREA) 0.5 -- 69. 周长字段与几何长度不一致 SHAPE_Length - PERIMETER 0.01 -- 70. 对象编号异常 OBJECTID 0 -- 71. 几何面积字段为空 SHAPE_Area IS NULL -- 72. 超长线要素排查 SHAPE_Length 10000 -- 73. 面积比值异常 AREA / SHAPE_Area 1.001 -- 74. 极小面且非零典型的碎屑 SHAPE_Area 1 AND SHAPE_Area 0 -- 75. 面积为零但周长不为零逻辑矛盾 AREA 0 AND PERIMETER 0SHAPE_Area和SHAPE_Length是文件地理数据库自动维护的几何字段对应面要素的面积和线要素的长度线要素用SHAPE_Length面要素同时有SHAPE_Area和SHAPE_Length。它们的好处是随几何变化自动更新坏处是不能手动改而且字段名就是这两个固定的拼写你改投影、换坐标系它们会跟着变。第 68、69 条那两行是我做拓扑检查的土办法。很多单位在数据交付时会带一份自己算的面积字段某次编辑之后几何变了但属性没同步就会出现“属性面积 10000 平方米、实际几何面积 9500 平方米”这种数据。用ABS一比就露馅比一个个打开看快得多。提示SHAPE_Area的单位跟你图层的坐标系有关地理坐标系下算出来是平方度没有实际意义。做面积核查前务必先把图层投影到投影坐标系比如 CGCS2000 的对应带号投影面积单位才是平方米。4.2 几何字段查询的限制与替代思路几何字段有个天然限制你不能直接查询SHAPE字段本身比如写SHAPE ...或者拿它做比较软件会报“字段不可用于查询”。能做比较的只有SHAPE_Area和SHAPE_Length这两个衍生字段想按几何形状本身筛选得走“按位置选择”或者空间查询那是另一套工具了。还有个容易忽略的点SHAPE_Area这类字段在部分操作后会“滞后”。比如你用“投影”工具刚转完坐标系字段值可能需要重新计算图层或刷新才更新。如果你发现面积明显不对别急着怀疑公式先把图层移除再重新加载一次很多时候问题就没了。这算不上什么高深技巧但排查问题时脑子里得有这根弦能省下不少无头苍蝇式的试错。5. 字段计算器里的 Python 表达式公式5.1 字符串处理类的 15 条表达式按属性选择只能筛不能改。真要批量改造数据得靠字段计算器的 Python 解析器。关键提醒Python 3 环境下用!字段名!引用字段值字符串要用str()转换Python 2 老环境里则要用unicode()这个差异不看清楚表达式会报一堆类型错误。# 76. 取前三个字符 !NAME![:3] # 77. 去掉首尾空格 !NAME!.strip() # 78. 去掉所有空格 .join(!NAME!.split()) # 79. 替换字符 !NAME!.replace(-, ) # 80. 编号左侧补零到6位 !CODE!.zfill(6) # 81. 统一大小写 !NAME!.upper() !NAME!.lower() # 82. 取首字 !NAME![0] # 83. 编码每两位插入短横线 -.join(!CODE![i:i2] for i in range(0, len(!CODE!), 2)) # 84. 去除左侧前导零 !CODE!.lstrip(0) # 85. 截取中间一段 !CODE![2:5] # 86. 按分隔符拆分取最后一段 !ADDR!.split(省)[-1] # 87. 号码右侧补齐到指定位数 !CODE![:6].ljust(12, 0) # 88. 拼接完整地址 !PROV! !CITY! !COUNTY! # 89. 把0开头的文本编号补回前导零 !CODE!.zfill(9) # 90. 表达式换行前先判断空值 !NAME!.strip() if !NAME! else 第 83 条那个“每两位插横线”的写法是我处理行政区划代码和行业分类代码时的常用套路。原始的 12 位码看着一长串插入分隔符后一眼能看出层级做人工核对时舒服很多。拆开看!CODE![i:i2]是按步长 2 切子串-.join(...)再用横线接起来理解了这个模板改成每三位、每四位都只是改个数字的事。第 90 条那种带判断的写法值得养成习惯。字段计算器遇到 NULL 值时会直接抛错一行表达式处理几万条记录跑到一半因为一个空值崩了前面白算。加个if !NAME! else 兜底就能平稳跑完。同样的道理涉及类型转换的表达式比如str(!OBJECTID!)尽量在转换前确认字段不是 NULL。第 88 条拼接地址时要注意Python 里字符串相加要求两边都是字符串如果!CITY!是数值型字段会直接报错得写成!PROV! str(!CITY!)。这个坑我在第一次做地址标准化的时候踩得结结实实报错信息说是“不支持的操作数类型”当时愣了半天才反应过来是字段类型的问题。5.2 条件赋值与数值换算的 10 条表达式字段计算器真正强大的地方是能在表达式里写条件逻辑一行顶过去好几十个手动编辑。# 91. 简单二分类 一级 if !AREA! 1000 else 二级 # 92. 多级分类嵌套 高 if !V! 100 else (中 if !V! 50 else 低) # 93. 平方米换算成亩 round(!SHAPE_Area! / 666.6667, 2) # 94. 平方米换算成公顷 round(!SHAPE_Area! / 10000, 2) # 95. 空值替换为默认文本 !NAME! if !NAME! else 未知 # 96. 提取年份 !DATE!.strftime(%Y) # 97. 生成统一编号 QG str(!OBJECTID!).zfill(5) # 98. 判断是否包含关键字 含河 if 河 in str(!NAME!) else 不含 # 99. 按百分比打标签 达标 if !RATE! 0.8 else 不达标 # 100. 用正则去掉所有空白字符 import re re.sub(r\s, , str(!NAME!))第 93 条那个 1 亩等于 666.6667 平方米的换算是土地行业里天天要用的。原始数据的面积字段动辄十几万位小数直接展示太难看round(..., 2)保留两位小数既清爽又够用。做耕地、林地面积统计的时候我一般会同时算出亩和公顷两个字段不同报表要的单位不一样省得来回折腾。第 96 条的日期提取要特别注意字段类型只有真正的日期型字段才能用.strftime()如果是文本型日期得先用datetime模块解析。这个前提条件不满足的话表达式会报“字符串对象没有该属性”处理前先看一眼字段类型。第 100 条用到了re模块字段计算器里可以在表达式上方的“预逻辑脚本代码”框里写import re然后表达式里直接调用。这是对付“混杂各种空格与特殊字符”的文本数据的终极武器。我处理过一批网上爬来的地址全角空格、半角空格、制表符混在一起re.sub(r\s, , ...)一把梭比手写一串replace干净太多。注意字段计算器一旦执行就写进数据里了尤其用“编辑会话”的时候。养成习惯先备份原始图层或者先用“新建字段”把结果算到新字段上确认无误再覆盖原字段。我见过太多人算错之后回来哭原始数据已经没了。6. 常见问题与排查技巧实录6.1 报错与结果异常的速查表属性查询翻来覆去就那么几个错我整理成表下次遇到直接对号入座。现象大概率原因处理办法表达式语法错误但不提示位置用了中文全角引号或括号输入法切英文重敲引号查询结果为空但明显有匹配数据字符串用了双引号字符串常量改单引号NAME 北京查不到字段里有首尾空格用TRIM(NAME) 北京或先清洗日期查询报类型错误数据源日期语法不对gdb 用DATE ...shp 用#...#IS NULL查不到结果Shapefile 里没有真 NULL改用 或 0数值比较结果离谱字段实际是文本型用CAST(... AS INTEGER)转换公式报“字段不存在”字段名拼写或大小写不符直接双击字段列表插入字段名查询特别慢卡住不动用了%xxx%前置通配缩小范围或改用标记字段NOT条件漏记录NULL 记录被排除拆成加OR IS NULL面积字段算出天文数字图层是地理坐标系先投影到投影坐标系再算这张表里字符串双引号那条是最常见的我把“字符串永远用单引号”当成口诀来记。图省事的办法是在“按属性选择”对话框里点“获取唯一值”让软件把字段值列出来直接双击填入引号它会自动补对比手敲安全得多。日期语法那条也值得多说一句。判断你的数据源该用哪种写法的土办法是先随便写一条DATE DATE 2024-01-01报错就换#2024-01-01#两个都不行再试TIMESTAMP。虽然土但快。看数据源类型这个动作熟练之后一眼就能判断不用试。6.2 我踩过的几个坑与实用心得先说一个折磨了我很久的问题中文字段名。有些项目交付的数据用中文命名字段比如“地块面积”“权属单位”。这种字段在查询里一定要用双引号包起来地块面积 1000不包直接报错。而且中文字段名在跨数据库、跨版本的迁移里特别容易出乱码我现在的习惯是一律在入库前把字段名改成英文或拼音一劳永逸。再说一个关于LIKE性能的实测。同样是筛选“名称包含 河”的记录在一个 30 万条记录的地名图层上NAME LIKE %河%跑了将近两分钟而我把“是否含河”事先用字段计算器算成 0/1 字段之后FLAG_RIVER 1只用了不到一秒。差距就是这么夸张。所以我的建议是凡是会反复查的关键字都提前算成标记字段这是拿时间换时间的典型操作一次性投入后面查多少次都赚。还有坐标系这个事很多新手栽在面积计算上。地理坐标系比如经纬度下SHAPE_Area算出来单位是平方度一个地块可能显示 0.0000001 这种数字一看就不对。解决办法在“数据管理工具”里找“投影”转到对应的投影坐标系面积单位才变成平方米。这一步不做后面所有的面积阈值筛选都是错的方向。我现在拿到任何新数据第一件事就是看坐标系养成条件反射了。最后分享一个批量核查的小技巧。当你手上有上百条筛选条件要跑比如按行政区逐个筛本地块一个个改表达式太慢。这时候用“图层属性”里的“定义查询”把常用的筛选条件存进去图层就只显示符合条件的要素需要切换时改一处就行比反复跑“按属性选择”高效得多。定义查询和按属性选择用的是同一套 SQL 语法前面这些公式原封不动搬过去就能用。这算是我个人做批量核查时最省力的一个习惯尤其做多部门数据比对的时候一个图层挂一个定义查询来回切换一眼就能看出差异。字段计算器那边也有个小窍门很多人不知道表达式框下方可以展开“代码块”写多行逻辑。当你的条件判断超过三层嵌套一行表达式写起来又长又容易错不如在代码块里定义个函数表达式里一行调用逻辑清爽调试也方便。这个用法处理复杂的编码转换、地址解析时特别顺手值得花十分钟熟悉一下。
返回列表