直接对地址字符串用substring(address,1,6)截取前6位当区域码极易出错,因地址含空格、括号、混写等非标格式;必须基于标准12位行政区划代码字段area_code才可安全使用:省级取substring(area_code,1,2),地级取substring(area_code,1,4),县级取substring(area_code,1,6),并需加length和regexp校验确保数据合规。

用SUBSTRING截取行政区划代码做分组的常见误区
直接对地址字符串用 SUBSTRING(address, 1, 6) 截取前6位当区域码,大概率统计错——中国行政区划代码(GB/T 2260)是层级编码,但业务表里的“地址”字段往往含括号、空格、省市区混写(如“广东省深圳市南山区科技园”),根本没法靠固定位置截取。
真正可用的起点是:**必须有标准的12位行政区划代码字段**(如 area_code),或先通过外部数据清洗补全。否则 SUBSTRING 只会放大脏数据的影响。
按省级/地级/县级分组的SUBSTRING写法与边界说明
假设你已有一列 area_code,值为标准12位数字(如广东深圳南山区是 440305,注意末尾6位补零后共12位),此时才能安全使用 SUBSTRING:
- 省级分组:取前2位 →
SUBSTRING(area_code, 1, 2)(如44代表广东) - 地级分组:取前4位 →
SUBSTRING(area_code, 1, 4)(如4403代表深圳) - 县级分组:取前6位 →
SUBSTRING(area_code, 1, 6)(如440305代表南山区)
注意:MySQL 中 SUBSTRING(str, pos, len) 的 pos 从1开始;PostgreSQL/SQL Server 要用 SUBSTR 或 LEFT,且索引从1起算一致。别写成 SUBSTRING(area_code, 0, 2) —— MySQL 里 pos=0 会返回空字符串。
销售额统计时必须加WHERE过滤空码和非法长度
area_code 字段常存在空值、短于6位(如只有“广东”)、或含字母(如“CN-440305”),不处理会导致分组混乱甚至NULL被归入同一组:
- 加长度校验:
WHERE LENGTH(TRIM(area_code)) = 12 - 加数字校验(MySQL):
AND area_code REGEXP '^[0-9]{12}$' - 排除全零码:
AND area_code != '000000000000'
漏掉这些,SUM(sale_amount) 可能把测试数据、占位符、错误导入记录全算进去,且难以排查。
关联行政区划表比硬编码更可靠
只靠 SUBSTRING 得到的是数字码,业务方看不懂“440305”是谁。与其在报表层拼接名称,不如 JOIN 标准行政区划维表:
SELECT p.province_name, c.city_name, SUM(t.sale_amount) AS total_sales FROM sales_table t JOIN area_dim c ON SUBSTRING(t.area_code, 1, 4) = c.city_code JOIN area_dim p ON SUBSTRING(t.area_code, 1, 2) = p.province_code WHERE LENGTH(t.area_code) = 12 GROUP BY p.province_name, c.city_name;
维表 area_dim 需含 province_code(2位)、city_code(4位)、county_code(6位)及对应中文名。这样既避免重复截取逻辑,又天然支持按省/市灵活切换,还能统一处理撤并区域(如“巢湖市”已撤销,维表中可标为失效)。
真正麻烦的从来不是 SUBSTRING 怎么写,而是确认那串数字到底是不是 GB/T 2260 编码、有没有随民政部最新公告更新。











