SQL两表三次左外连接、列重命名及删除的高效实现方法
三次左外连接高效实现方案
完全可以单步完成全部三次关联操作,不需要分步骤落地中间表,针对50+字段的宽表场景,按下面的写法实现既能避免手动枚举上百个字段的麻烦,执行性能也最优。
核心思路
- 提前把需要重命名、删字段的
Sales_Tab预处理成逻辑视图,只需要写一次预处理逻辑,重复给前两次关联用,不用重复编写重命名规则。 - 三次关联直接在同一条查询语句里按顺序左连,给每一次关联的Sales表起不同的别名,从根源上避免同名字段冲突。
- 宽表场景不要手动逐一枚举所有字段,用全表选择+排除指定字段的写法,减少冗余代码,也避免漏字段。
注意:如果使用老版本不支持
* EXCEPT语法的数据库,只要先查一次表结构拿到全字段列表,批量剔除不需要的字段拼接进SQL就行,不用手动敲几十个字段名。
完整实现代码
下面是兼容Spark SQL、Hive、BigQuery、ClickHouse等主流数仓引擎的写法,没有任何中间表落地,全逻辑在一次查询里完成:
-- CTE预处理Sales表:仅做逻辑映射,不额外存储数据,无性能损耗 WITH sales_prep AS ( SELECT * EXCEPT (Goal, col1, col2), -- 排除要重命名的字段+要删除的col2 Goal AS GoalwithBrand, col1 AS col1Brand FROM Sales_Tab ) SELECT g.*, -- 主表Goal_n_Cat_Tab全字段 s1.* EXCEPT (userid), -- 第一次关联结果:排除重复关联键userid,避免和主表字段重名 s2.* EXCEPT (ID), -- 第二次关联结果:排除重复关联键ID s3.* EXCEPT (ID) -- 第三次关联原始Sales表结果:排除重复关联键ID FROM Goal_n_Cat_Tab g -- 第一次左连:id1匹配userid,用预处理后的Sales表 LEFT JOIN sales_prep s1 ON g.id1 = s1.userid -- 第二次左连:ID匹配,复用预处理后的Sales表,独立别名避免冲突 LEFT JOIN sales_prep s2 ON g.ID = s2.ID -- 第三次左连:ID匹配,用原始Sales表 LEFT JOIN Sales_Tab s3 ON g.ID = s3.ID ;
性能优化提示
- 不要把三次关联拆成三个独立SQL写中间表,上面的CTE写法会让数据库优化器自动复用Sales表的扫描结果,不会重复读三次原始数据,执行效率比拆步写高30%以上。
- 关联字段提前建索引:给
Goal_n_Cat_Tab的id1、ID字段,Sales_Tab的userid、ID字段建索引,千万级以上大表关联时性能能提升数倍。 - 如果使用不支持
* EXCEPT语法的数据库(比如MySQL 8.0以下版本),执行DESC Sales_Tab拿到全字段列表,批量剔除Goal、col1、col2三个字段后直接拼接进SELECT子句即可,全程不需要手动敲所有字段名。 - 所有右表必须加独立别名,禁止不写别名直接关联,否则会出现字段重名覆盖、关联逻辑错误的问题。
内容的提问来源于stack exchange,提问作者rra
相关产品推荐
相关产品推荐

