
本文介绍如何使用 sql 的 union 操作高效提取多个电话号码列(如 tel1–tel4)中的全部唯一数值,适用于无法修改源表结构但需构建独立号码字典表的场景。
本文介绍如何使用 sql 的 union 操作高效提取多个电话号码列(如 tel1–tel4)中的全部唯一数值,适用于无法修改源表结构但需构建独立号码字典表的场景。
在实际数据库开发中,常遇到类似「电话目录表」的宽表结构:同一记录包含多个相似语义的列(如 Tel1, Tel2, Tel3, Tel4),而业务需求并非按行去重,而是将所有列中出现过的全部电话号码汇总后去重——即每个号码仅保留一次,无论它出现在哪一列、哪一行。
此时,DISTINCT 单独作用于某列或 SELECT DISTINCT * 均无法满足需求:前者只能对单列去重,后者仍以整行为单位判重。正确解法是利用 SQL 的 UNION 特性:UNION 在合并多个结果集时自动去除重复值(等价于 UNION DISTINCT),且不要求各子查询列数相同(此处均为单列,天然兼容)。
✅ 推荐查询(获取唯一号码列表):
SELECT Tel1 AS number FROM your_table UNION SELECT Tel2 FROM your_table UNION SELECT Tel3 FROM your_table UNION SELECT Tel4 FROM your_table;
⚠️ 注意:UNION 会隐式排序并去重;若需保持原始顺序(不推荐),可改用 UNION ALL + 外层 GROUP BY,但本场景以去重为首要目标,UNION 最简洁可靠。
✅ 一步创建新表并填充唯一号码(推荐用于一次性初始化):
CREATE TABLE phone_directory (
id INT PRIMARY KEY AUTO_INCREMENT,
number VARCHAR(20) NOT NULL UNIQUE,
remark TEXT DEFAULT NULL
) AS
SELECT Tel1 AS number FROM your_table
UNION
SELECT Tel2 FROM your_table
UNION
SELECT Tel3 FROM your_table
UNION
SELECT Tel4 FROM your_table;该语句同时完成两件事:
- 定义新表结构(含主键、唯一约束及扩展字段预留);
- 直接插入去重后的全部号码。后续即可在 phone_directory 表中为每个号码添加描述、归属产品、状态等元信息,供前端关联查询使用。
? 扩展提示:
- 若后续新增电话列(如 Tel5),只需在 UNION 链中追加一行 SELECT Tel5 FROM your_table;
- 对超大表(千万级),虽问题明确“不关注性能”,但仍建议在执行前为 Tel1–Tel4 各列添加索引(仅读操作受益有限,但可加速后续关联查询);
- 在 phpMyAdmin 或 MySQL Workbench 中执行时,确保结果以“显示所有”模式查看,避免默认截断。
通过此方法,你无需人工遍历原始长表,即可精准、可复现地生成标准化号码字典,为前端展示附加信息奠定健壮的数据基础。

















