ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

机场三字代码编码规则与数据治理实战:从IATA代码到SQL清洗

机场三字代码编码规则与数据治理实战:从IATA代码到SQL清洗 简介这是一份系统整理机场三字代码的速查文档覆盖国内及部分国际主要机场适合航空从业者、旅游出行人员、民航专业学生及需要频繁查询机场代码的商务旅客使用。文档以表格形式将城市、机场名称与三字代码逐项对照从北京首都PEK、上海浦东PVG到昭通ZAT、阿拉木图ALA等均有收录检索直观。压缩包内为单个Word文档约22KB体量轻巧按城市拼音顺序排列。除代码对照表外还简要梳理了三字代码的组成规则、分类方式、命名标准及应用场景帮助读者理解代码背后的逻辑例如国内代码多以汉语拼音为基础、国际代码由国际航空运输协会统一制定等。已有916人浏览学习既可作为日常出行、机票预订时的实用工具也可为民航类考试或业务培训提供参考。1. 机场三字代码表PEK、BJS和SHA背后的数据坑订票系统里最容易被忽略的字段就是机场三字代码。PEK是北京首都机场BJS是北京城市代码SHA是虹桥PVG是浦东。如果业务系统把“城市”和“机场”混在一个字段里出票、结算、航段拼接都会出错。我手里的这份中国机场三字代码表覆盖了从阿勒泰到遵义的百多个机场代码看起来只是“城市名三字码”的二维表实际拿去对接航班数据时命名规则、重复代码、旧称残留全是坑。适合做机票分销、机场数据治理、航班管家的工程师直接拿来当静态字典也适合刚接触民航数据的人理解IATA代码的真实形态。2. 机场三字代码的编码规则拆解拼音、旧译名与城市码2.1 代码来源不是一套规则把这份表摊开看三字代码至少混着四种来源。第一种是纯拼音首字母AAT阿勒泰、AKU阿克苏、HFE合肥这类城市名拼音首字母直接拼成三个字最容易理解。第二种是拼音首字母和元音混拼比如HAK海口按拼音应该是H、K中间多了个AWUH武汉同理WuHan取了WUH。第三种是历史旧译名残留KOW赣州、SWA汕头、TAO青岛、PEK北京全是这种赣州旧称Kanchow汕头旧称Swatow青岛旧称Tsingtao北京旧称Peking。第四种是城市码BJS北京不指向某个具体机场只表示“北京的某个机场”。这套规则混乱是历史原因。IATA代码不是中国民航局单方面定的而是航空公司、机场和IATA三方确认后固定下来的。早期中国机场对外通信多用邮政式拼音或威妥玛拼音代码沿用旧译名后来新建机场才直接用拼音。所以不要试图用当前拼音反推所有代码KOW里既没有G也没有Z硬套规则只会误判。2.2 用脚本快速标识“不规则代码”拿到新代码表时我一般先写个小脚本把“可能是旧译名”的条目筛出来再人工核对。下面这个脚本用拼音首字母做初步判别# samples: (城市名, 三字码, 拼音首字母) samples [ (阿勒泰, AAT, A), (海口, HAK, H), (南昌, KHN, N), (赣州, KOW, G), (宁波, NGB, N), (黄山, TXN, H), ] def check_rule(city, code, initial): # 统计三字码中命中拼音首字母的次数 hit sum(1 for ch in code if ch initial) return hit for city, code, initial in samples: hit check_rule(city, code, initial) if hit 1: print(f{city} {code}: 包含拼音首字母{initial}半规则) else: print(f{city} {code}: 完全不匹配拼音首字母需查旧称)这里的逻辑很简单统计三字码里出现城市拼音首字母的次数。命中一次以上只代表“有点关系”完全没命中才标记为旧译名候选。赣州KOW就因为没有G被识别出来TXN黄山也没有H。这个脚本不适合直接当生产工具但用来给上游数据做初筛能把明显异常的代码挑出来省去逐行翻表的时间。2.3 规则命中的真实分布把整份代码表按上述逻辑跑一遍“完全匹配拼音首字母”的只占大约三成剩下的大部分是半规则和旧译名。半规则主要是城市名双字复合比如KMG昆明、HRB哈尔滨这类代码是取了前两个字的声母和某个元音无法用统一公式生成。三字码城市来源推断说明PEK北京首都机场旧译名 Peking机场码精确到首都机场BJS北京拼音 Beijing 缩写城市码不精确到机场KOW赣州旧译名 Kanchow代码和拼音完全无关SWA汕头旧译名 Swatow代码来自历史拼写HGH杭州旧译名 Hangchow实际拼写是HangzhouSHA上海虹桥Shanghai 英文缩写代码中保留了SH做数据治理时我建议在这张表旁边加一列“编码来源”标记是拼音、旧译名还是城市码。后续做模糊匹配、代码补全时可以直接按这个字段调整权重而不是把所有代码当成同一类规则处理。3. 机场三字代码表落库SQL建表与联表查询实战3.1 字段设计要能区分城市码和机场码把这份代码表导入MySQL之前先想清楚字段。最简单的表是两个字段code和city但实际使用时会发现城市名无法承载“机场”和“城市”两种语义。BJS北京、PEK北京首都机场都叫“北京”直接GROUP BY city会把它们混在一起。我一般增加code_type字段和airport_name字段code_type标记是城市码还是机场码airport_name存具体机场名允许为空。CREATE TABLE airport_codes ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, code CHAR(3) NOT NULL COMMENT IATA三字码, city VARCHAR(50) NOT NULL COMMENT 城市名/行政区名, airport_name VARCHAR(100) DEFAULT NULL COMMENT 具体机场名城市码为空, code_type TINYINT NOT NULL DEFAULT 0 COMMENT 0机场码1城市码, remark VARCHAR(255) DEFAULT NULL COMMENT 备注旧译名/多机场, UNIQUE KEY uk_code (code), KEY idx_city (city) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字段说明code用CHAR(3)固定长度IATA代码固定三个半角大写字母CHAR(3)的存储效率比VARCHAR高也避免读出带空格的值。code_type是核心字段城市对航线查询时只用code_type1精确机场换算是0。city列用来做中文城市维度的聚合索引必加后面联表全靠它。3.2 批量导入与基础查询导入时按原始数据逐行INSERT注意北京、上海这种多机场城市要拆成多行BJS、PEK分两行SHA、PVG分两行city字段都填北京或上海靠airport_name区分。INSERT INTO airport_codes (code, city, airport_name, code_type, remark) VALUES (BJS, 北京, NULL, 1, 北京城市代码), (PEK, 北京, 北京首都机场, 0, 旧译名Peking), (SHA, 上海, 上海虹桥机场, 0, 虹桥机场), (PVG, 上海, 上海浦东机场, 0, 浦东机场), (KOW, 赣州, NULL, 0, 旧译名Kanchow), (SWA, 汕头, NULL, 0, 旧译名Swatow), (CAN, 广州, NULL, 0, 旧译名Canton);导入后先跑两个查询验证数据质量。一个是查所有A开头代码一个是查多机场城市。-- 查A开头机场验证索引 SELECT code, city, airport_name, code_type FROM airport_codes WHERE code LIKE A%; -- 找出有一城多码的城市 SELECT city, COUNT(*) AS code_count FROM airport_codes GROUP BY city HAVING COUNT(*) 1;LIKE A%会走idx_city吗不会它会全表扫描但因为表数据量只有一百多行实际查询耗时基本为零。GROUP BY加HAVING是找出多机场城市最直接的方式北京、上海、西安这类城市会出现在结果里。这里有一个坑city列必须保证录入时没有前后空格否则GROUP BY会把“北京”和“北京 ”拆成两个组。3.3 联表补全航班订单的城市信息代码表建好之后最常用的操作是给航班订单表补城市。机票订单通常只存三字码不存中文城市名展示时再关联代码表。-- 模拟航班订单表 CREATE TABLE flight_orders ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, order_no VARCHAR(32) NOT NULL, dep_code CHAR(3) NOT NULL, arr_code CHAR(3) NOT NULL ); INSERT INTO flight_orders (order_no, dep_code, arr_code) VALUES (FD20240001, PEK, SHA), (FD20240002, BJS, CAN), (FD20240003, KOW, PVG); -- 联表查出出发城市和到达城市 SELECT o.order_no, d.city AS dep_city, a.city AS arr_city, a.airport_name AS arr_airport FROM flight_orders o LEFT JOIN airport_codes d ON o.dep_code d.code LEFT JOIN airport_codes a ON o.arr_code a.code;这里用LEFT JOIN而不是INNER JOIN原因是订单里可能出现代码表里没有的三字码比如国际航班代码或已关闭的机场。LEFT JOIN能把未匹配的订单保留下来arr_city为NULL的才是要重点排查的数据。dep_code和arr_code都关联同一张表所以别名d和a缺一不可否则SQL会报列名歧义。查询结果中FD20240002订单的dep_code是BJS这是城市码它只适合做城市对统计不能用于航站楼级别计算。注意CHAR(3)在MySQL默认排序规则下查询不区分大小写where codepek也能查到PEK。IATA标准要求大写但做数据清洗时不要把大小写当成过滤条件。4. 多机场城市的代码歧义与脏数据清洗方法4.1 城市码和机场码混用的场景BJS、PEK都对应北京但语义完全不同。BJS属于城市码在航信系统中代表“北京地区任意机场”常用于城市对报价PEK是精确的首都机场。SHA和PVG同理一个虹桥一个浦东。如果业务只关心航线连通性用BJS没错如果要做行李转盘、值机柜台这种颗粒度的业务必须用PEK或者PKX。数据仓库里最常见的问题是同一个订单在不同时间落库一次存BJS一次存PEK按城市汇总时就产生了两条记录。我见过的处理方式是增加一张“城市码映射表”把BJS映射到北京再单独维护一张“机场归属表”-- 城市码归属映射 SELECT o.order_no, COALESCE(a.city, d.city) AS route_city FROM flight_orders o LEFT JOIN airport_codes a ON o.arr_code a.code LEFT JOIN airport_codes d ON o.dep_code d.code;COALESCE的作用是当机场码匹配失败时回退到城市码这里arr_code和dep_code都关联代码表机场码和城市码都能命中city字段最终route_city就是统一的城市粒度。这个技巧比先判断code_type再分表查询简单得多少写一半代码。4.2 易混淆代码清单三字码的相似性是脏数据的主要来源。下面这份对照从代码表中整理出来全是实际会碰到的坑易错代码正确代码城市/机场出错场景CDGCGD常德常德写成巴黎戴高乐NGBNNG宁波/南宁两个代码后两位互为交换HAKHRB海口/哈尔滨H开头双字城市极易混TSNTXN天津/黄山首字母相同后缀相似XIYXIN西安咸阳/兴宁X开头一组代码整体相似XICXIL西昌/锡林浩特中间字母I/L相近这些错误在录入时几乎无法靠人工发现CDG和CGD只差一个字母但连城市带国家全变了。处理办法是在写入订单表前用一个“代码白名单”约束不在白名单内的三字码直接拒绝入库或进入待审核队列。4.3 用编辑距离自动校验候选代码针对上述混淆写一个基于编辑距离的校验脚本输入一个不存在的代码输出最接近的合法代码。def edit_distance(s1, s2): m, n len(s1), len(s2) dp [[0] * (n 1) for _ in range(m 1)] for i in range(m 1): dp[i][0] i for j in range(n 1): dp[0][j] j for i in range(1, m 1): for j in range(1, n 1): cost 0 if s1[i - 1] s2[j - 1] else 1 dp[i][j] min( dp[i - 1][j] 1, dp[i][j - 1] 1, dp[i - 1][j - 1] cost ) return dp[m][n] valid_codes [CGD, NGB, NNG, HAK, HRB, TSN, TXN, XIY, XIC, XIL] def suggest(bad_code, candidates, threshold2): return sorted( [(c, edit_distance(bad_code, c)) for c in candidates], keylambda x: x[1] )[:threshold] print(suggest(CDG, valid_codes)) print(suggest(NGB, valid_codes))输出结果是[(CGD, 1), (NNG, 3)]CDG距离CGD仅1距离其他代码都大于2说明用户大概率把常德打成了CDG。脚本里threshold参数控制返回候选数量我一般设为2再多就没意义了。这个校验可以挂在数据接入层的消息队列上也可以离线批量跑历史数据。5. 用Pandas给航班表批量标注城市map和merge的取舍5.1 先构建映射字典拿到的代码表是二维表航班数据通常也是CSV用Pandas处理最直接。先把三字码转成字典避免反复读表import pandas as pd # airport_codes.csv 至少包含 code/city/code_type 三列 df_code pd.read_csv(airport_codes.csv, dtype{code: str}) # 构建 三字码 - 城市 的映射 code2city df_code.set_index(code)[city] # 航班表只保留需要的列 df_flight pd.read_csv( flights.csv, dtype{dep_code: str, arr_code: str} ) df_flight[arr_city] df_flight[arr_code].str.strip().map(code2city)dtype参数必须指定为str否则“SHA”这类字母串在某些CSV里可能被读成NaN或自动转类型。map操作在Pandas里是哈希查找一百多万行航班数据几个毫秒就能完成比逐行apply快两个数量级。arr_code列做strip是防止“PEK ”带空格导致匹配失败。5.2 没有匹配上的代码单独处理missed df_flight[df_flight[arr_city].isna()] print(f未匹配行数: {len(missed)}) print(missed[arr_code].value_counts().head(20))未匹配的原因主要有三种国际机场代码不在表中、南苑这类已关闭机场、原始数据里就有错码。把missed单独导出让业务核对核对结果分成两类一类补充到机场代码表一类是真正的脏数据。这里有一个小技巧如果业务逻辑只认城市不认具体机场map之前先把code_type 0的机场码过滤掉因为PEK和BJS映射到同一个城市会造成重复计算先过滤避免后面对数对不上。这种基于静态代码表的映射方式胜在简单可靠不需要外部API离线也能运行。后续如果代码表更新只需重新读取CSV再跑一遍map全流程不需要改代码。本文还有配套的精品资源点击获取
返回列表