ODPS JOIN(MaxComputer) 与 Oracle JOIN 用法对比

目录

    • [一、基本 JOIN 类型](#一、基本 JOIN 类型)
      • [1. 单独一个 `JOIN` 等价于 `INNER JOIN`](#1. 单独一个 JOIN 等价于 INNER JOIN)
      • [2. `LEFT JOIN` / `RIGHT JOIN` 用法一致](#2. LEFT JOIN / RIGHT JOIN 用法一致)
      • [3. 关联键重复导致数据翻倍](#3. 关联键重复导致数据翻倍)
    • [二、ODPS 与 Oracle 的主要差异](#二、ODPS 与 Oracle 的主要差异)
      • [1. `(+)` 语法差异(重要)](#1. (+) 语法差异(重要))
      • [2. 半连接示例:`LEFT SEMI JOIN`](#2. 半连接示例:LEFT SEMI JOIN)
      • [3. `LEFT ANTI JOIN`(ODPS 特有)](#3. LEFT ANTI JOIN(ODPS 特有))
    • [三、多表 JOIN 顺序与优化](#三、多表 JOIN 顺序与优化)
    • 四、完整示例对比
    • 五、注意事项汇总

ODPS(MaxCompute)的 JOIN 语法与 Oracle 高度相似,但在一些细节上存在差异。以下将逐一说明。

一、基本 JOIN 类型

JOIN 类型 ODPS 语法 Oracle 语法 说明
内连接(INNER JOIN) JOIN 或 INNER JOIN JOIN 或 INNER JOIN 两者完全一致,只返回匹配的行。
左外连接(LEFT JOIN) LEFT JOIN 或 LEFT OUTER JOIN LEFT JOIN 或 LEFT OUTER JOIN 返回左表全部行,右表无匹配则为 NULL。
右外连接(RIGHT JOIN) RIGHT JOIN 或 RIGHT OUTER JOIN RIGHT JOIN 或 RIGHT OUTER JOIN 返回右表全部行,左表无匹配则为 NULL。
全外连接(FULL JOIN) FULL JOIN 或 FULL OUTER JOIN FULL JOIN 或 FULL OUTER JOIN 返回两表全部行,无匹配的一侧为 NULL。
交叉连接(CROSS JOIN) CROSS JOIN CROSS JOIN 返回笛卡尔积。
半连接 / 反连接 LEFT SEMI JOIN、LEFT ANTI JOIN(ODPS特有) EXISTS / NOT EXISTS 或 IN / NOT IN ODPS 提供了专门的半连接语法,性能更好。

1. 单独一个 JOIN 等价于 INNER JOIN

sql 复制代码
-- ODPS 与 Oracle 一致
SELECT *
FROM table_a a
JOIN table_b b ON a.id = b.id;
-- 等价于
SELECT *
FROM table_a a
INNER JOIN table_b b ON a.id = b.id;

2. LEFT JOIN / RIGHT JOIN 用法一致

sql 复制代码
-- 左连接:保留左表所有记录
SELECT a.id, a.name, b.order_date
FROM customers a
LEFT JOIN orders b ON a.id = b.cust_id;

3. 关联键重复导致数据翻倍

无论 ODPS 还是 Oracle,只要 JOIN 的关联键在任一侧存在重复值,结果行数都可能翻倍(相当于一对多或多对多)。

sql 复制代码
-- 左表:id=1 出现两次
-- 右表:id=1 出现三次
-- 结果会产生 2×3 = 6 行 id=1 的记录
SELECT *
FROM left_table a
JOIN right_table b ON a.id = b.id;

注意 :若需避免数据翻倍,可提前去重或使用 DISTINCT、聚合函数等。

二、ODPS 与 Oracle 的主要差异

差异点 ODPS Oracle
旧式外连接语法((+)) 不支持 (+) 语法 支持 WHERE a.id = b.id(+) 表示左外连接
半连接语法 LEFT SEMI JOIN / LEFT ANTI JOIN 无直接等价语法,需用 EXISTS / NOT EXISTS
JOIN 条件写法 必须使用 ON 子句,不支持 USING 支持 USING(column) 简化相同列名关联
NULL 比较行为 标准 SQL:NULL = NULL 结果为 NULL(不匹配) 相同
MAPJOIN 提示 支持 /*+ MAPJOIN(small_table) */ 优化小表 支持 /*+ USE_HASH(table) */ 等不同提示

1. (+) 语法差异(重要)

Oracle 允许在 WHERE 中使用 (+) 表示外连接,ODPS 不支持 ,必须使用标准的 LEFT/RIGHT/FULL JOIN。

sql 复制代码
-- Oracle 旧式语法(不推荐,但可用)
SELECT *
FROM emp e, dept d
WHERE e.dept_id = d.dept_id(+);   -- 左外连接

-- ODPS 必须改写为:
SELECT *
FROM emp e
LEFT JOIN dept d ON e.dept_id = d.dept_id;

2. 半连接示例:LEFT SEMI JOIN

ODPS 的 LEFT SEMI JOIN 只返回左表中与右表匹配的记录,且不返回右表任何列(类似 EXISTS)。

sql 复制代码
-- ODPS:查询有订单的客户(不关心订单详情)
SELECT a.id, a.name
FROM customers a
LEFT SEMI JOIN orders b ON a.id = b.cust_id;

-- Oracle 等价写法:
SELECT a.id, a.name
FROM customers a
WHERE EXISTS (SELECT 1 FROM orders b WHERE a.id = b.cust_id);

3. LEFT ANTI JOIN(ODPS 特有)

返回左表中没有 匹配右表的记录(类似 NOT EXISTS)。

sql 复制代码
-- ODPS:查询从未下过订单的客户
SELECT a.id, a.name
FROM customers a
LEFT ANTI JOIN orders b ON a.id = b.cust_id;

三、多表 JOIN 顺序与优化

  • ODPS :优化器会自动重排 JOIN 顺序,但可通过 /*+ MAPJOIN(table) */ 强制将小表加载到内存。
  • Oracle :优化器基于统计信息选择最优顺序,也可使用 ORDERED 提示强制顺序。

MAPJOIN 示例(ODPS):

sql 复制代码
SELECT /*+ MAPJOIN(dim_date) */ *
FROM fact_sales a
JOIN dim_date b ON a.date_key = b.date_key;

四、完整示例对比

场景:员工表(emp)与部门表(dept)左连接,获取所有员工及其部门名称。

ODPS:

sql 复制代码
SELECT e.empno, e.ename, d.dname
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno;

Oracle(标准语法相同,也支持旧式):

sql 复制代码
-- 标准语法(推荐)
SELECT e.empno, e.ename, d.dname
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno;

-- 旧式语法(仅 Oracle)
SELECT e.empno, e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno = d.deptno(+);

五、注意事项汇总

  1. 关联键重复导致数据膨胀:这是 SQL JOIN 的通用行为,并非 ODPS 或 Oracle 特有。务必检查关联键的唯一性。
  2. NULL 值处理 :NULL 与任何值(包括 NULL)比较均为 NULL,导致不匹配。若需将 NULL 视为相等,需使用 NVL 或 COALESCE 转换。
  3. 性能优化 :大表 JOIN 时,ODPS 中常用 MAPJOIN 提示;Oracle 中则常用 USE_HASH 或 USE_NL。
  4. 字符串类型隐式转换:ODPS 对隐式转换限制较严,建议显式转换类型;Oracle 较宽松但可能引发索引失效。
  5. 分区表 JOIN :ODPS 中 JOIN 前尽量裁剪分区(WHERE partition_col = ...),可大幅减少数据扫描量。

ODPS 的 JOIN 核心功能与 Oracle 保持一致 ,只需注意 (+) 旧语法不支持、以及半连接语法的差异即可轻松迁移。建议统一使用标准 SQL 的 JOIN ... ON 语法。

相关推荐
Decay__23 分钟前
05_MySQL 常用 SQL 大全 —— 诊断、管理、优化辅助 SQL 与三大系统库速查
运维·数据库·sql·mysql·架构
小徐不徐说5 小时前
C++ 接口与插件设计:从工厂注册到 Qt 动态插件
数据库·c++·qt·系统架构·程序设计
论文复现现场5 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
Decay__6 小时前
04_MySQL DBA 日常运维手册 —— 会话管理、锁与阻塞、事务监控、慢查询与日志巡检
运维·数据库·sql·mysql·架构
心梦缘-雪雁7 小时前
SQL Server 查询数据存在哪个表里
数据库
lusklusklusk8 小时前
Python 巡检脚本:进程运行状态、数据库写入时效检查及邮件通知与告警
数据库·python·oracle
GeW9 小时前
产业新优势基础软件的人才底盘,从Linux与数据库开始
linux·数据库
SelectDB9 小时前
Doris Arrow Flight SQL 高速读取协议实战:与 Snowflake 客户端取数链路对照
大数据·数据库·数据分析
曼岛_9 小时前
[图解密码学]第4章 古典密码
java·数据库·密码学
瀚高PG实验室10 小时前
HGDB V9.0.5 .pgpass 免密登录提示 IsEncryptNon-base64 encoding 警告处理
数据库·postgresql·瀚高数据库