将含嵌套子查询的Oracle风格查询转换为ANSI标准SQL
Oracle风格嵌套子查询转ANSI标准SQL方法
原语句逻辑梳理
原查询是Oracle中常见的关联标量子查询写法,没有显式声明连接类型,执行逻辑可以拆解为以下步骤:
- 主查询从
VIEW3(别名TABLE3)遍历每一行数据,返回ID字段 - 对
VIEW3的每一行,先到VIEW2(别名TABLE2)中匹配ID相等的记录,取出对应的COL2值 - 再到
VIEW2中匹配COL3相等的记录,取出对应的COL3值 - 最后拿着取出的COL2、COL3值到
VIEW1(别名TABLE1)中匹配对应记录,取出COL1作为查询的第二列返回
注意:原写法存在冗余和隐式风险:两次独立查询VIEW2的逻辑本质是同一条关联规则,且如果VIEW2或VIEW1匹配到多条记录,原语句会直接抛出「单行子查询返回多行」的运行时错误。
转换后的ANSI标准SQL
原标量子查询的行为和LEFT JOIN完全一致:关联匹配不到时COL1返回NULL,且保留VIEW3的所有行,转换后的显式连接写法如下:
SELECT t3.ID, t1.COL1 FROM VIEW3 t3 -- 关联VIEW2,合并原两个子查询的匹配条件 LEFT JOIN VIEW2 t2 ON t2.ID = t3.ID AND t2.COL3 = t3.COL3 -- 关联VIEW1,匹配对应字段取值 LEFT JOIN VIEW1 t1 ON t1.COL2 = t2.COL2 AND t1.COL3 = t2.COL3
对齐原逻辑的补充说明
如果需要100%兼容原Oracle语句的单行返回约束,避免JOIN后出现多行重复数据,可以对关联的视图做去重预处理,写法如下:
SELECT t3.ID, t1.COL1 FROM VIEW3 t3 LEFT JOIN ( SELECT DISTINCT ID, COL2, COL3 FROM VIEW2 ) t2 ON t2.ID = t3.ID AND t2.COL3 = t3.COL3 LEFT JOIN ( SELECT DISTINCT COL1, COL2, COL3 FROM VIEW1 ) t1 ON t1.COL2 = t2.COL2 AND t1.COL3 = t2.COL3
- 上述写法只需要访问VIEW1、VIEW2各一次,相比原嵌套子查询的多次访问性能更优
- 所有连接类型显式声明,在PostgreSQL、MySQL、SQL Server等所有支持ANSI SQL的数据库中都可以直接运行,不需要做语法适配
内容的提问来源于stack exchange,提问作者user1227793
相关产品推荐
相关产品推荐

