
本文介绍如何使用 sql 的 union 操作高效提取多个电话号码列(如 tel1–tel4)中的全部唯一数值,避免重复,适用于不可修改源表但需构建新维度表的场景。
本文介绍如何使用 sql 的 union 操作高效提取多个电话号码列(如 tel1–tel4)中的全部唯一数值,避免重复,适用于不可修改源表但需构建新维度表的场景。
在数据库设计中,常遇到类似“宽表”结构:同一实体(如产品)的多个属性被横向展开为多列(例如 Tel1, Tel2, Tel3, Tel4),而业务需求却要求将这些列中的所有不重复的原子值汇总为一个独立列表——例如为每个唯一电话号码建立关联元数据的新表(如归属部门、服务状态等)。此时,DISTINCT 作用于整行无法满足需求,必须跨列“纵向折叠”再去重。
核心解决方案是利用 UNION(而非 UNION ALL)语义:UNION 自动合并多个结果集并去除重复项,天然适配“多列取唯一值”的场景。
✅ 正确写法(推荐):
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 会隐式去重且按字段类型排序(多数引擎默认升序),若需严格保持原始顺序或排除 NULL,可添加 WHERE TelX IS NOT NULL 条件。
✅ 一步创建新表(含数据):
CREATE TABLE phone_directory 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;
该语句在 MySQL 中可直接执行,生成带主键可选、无索引的新表;后续建议手动添加主键与索引提升查询性能:
ALTER TABLE phone_directory ADD PRIMARY KEY (number);
? 关键说明:
- UNION 是标准 SQL,兼容 MySQL、PostgreSQL、SQL Server、SQLite 等主流数据库;
- 若列名类型不一致(如混合字符串与数字),需显式 CAST() 统一类型;
- 对超大表(千万级),虽为一次性任务,仍建议在低峰期执行,并确认临时空间充足;
- 本方案完全绕过源表结构限制,符合“不可修改原表”的硬性约束,与第三方系统无缝共存。
最终得到的 phone_directory 表即可作为前端展示的电话元数据中心——当用户点击某条记录的 Tel2 = '1234' 时,后端只需 SELECT * FROM phone_directory WHERE number = '1234' 即可加载扩展信息,实现解耦与可维护性升级。










