【问题标题】:Native Outer Join to Two Tables - How to rewrite to ANSI Join? [closed]两个表的本机外连接 - 如何重写为 ANSI 连接? [关闭]
【发布时间】:2020-10-16 09:07:53
【问题描述】:

我在 Oracle 19.0 中使用 Oracle 原生(经典)连接表示法编写了以下查询

SELECT   last_name, e.job_id, department_name, j.job_id, job_title
FROM employees e, departments d, jobs j
WHERE e.department_id(+) = d.department_id
AND e.job_id(+) = j.job_id;

返回结果(参见下面的示例数据)

LAST     JOB_ID DE     JOB_ID JO
---- ---------- -- ---------- --
Aaaa          1 D1          1 J1
Bbbb          2 D1          2 J2
                D2          1 J1
                D2          2 J2
                D2          3 J3
                D1          3 J3

什么是 Oracle ANSI 格式的这种连接的等价物(我努力争取,因为这是本网站上的 cmets 推荐的无数次)。

我能想象的最好的方法是跟踪查询

SELECT   e.last_name, e.job_id, d.department_name, j.job_id, j.job_title 
FROM employees e RIGHT JOIN departments d
ON(e.department_id = d.department_id)
RIGHT JOIN jobs j on  e.job_id = j.job_id;

但结果却大不相同,这让我很困惑。

LAST     JOB_ID DE     JOB_ID JO
---- ---------- -- ---------- --
Aaaa          1 D1          1 J1
Bbbb          2 D1          2 J2
                            3 J3 

我知道 Oracle 原生语法中的第一个查询是一项新功能,因为版本 11.2 中的此查询失败

 ORA-01417: a table may be outer joined to at most one other table

我的样本数据如下

create table employees as 
select 1 id, 'Aaaa' last_name, 1 department_id, 1 job_id from dual union all
select 2 id, 'Bbbb' last_name, 1 department_id, 2 job_id from dual;

create table departments as 
select 1 department_id, 'D1' department_name from dual union all
select 2 department_id, 'D2' department_name from dual;

create table jobs as 
select 1 job_id, 'J1' job_title from dual union all
select 2 job_id, 'J2' job_title from dual union all
select 3 job_id, 'J3' job_title from dual;

【问题讨论】:

  • 大约 15(!) 年前我停止使用旧的 Oracle 连接语法(你也应该这样做),因此我不再那么熟悉它了。但是,据我记得应该是e.department_id = d.department_id(+) AND e.job_id = j.job_id(+) 才能获得相同的结果。
  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)的 SQL,并以表格格式作为代码输入。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。
  • 您研究的 1 个具体的非重复问题是什么? PS手册和许多其他地方,包括这里的问题,都说明了关键字外连接的工作原理以及Oracle外连接在基本情况下的工作原理。遵循手册或其他权威文档并询问您是如何应用它的,从简单的案例开始——截断代码。如果您没有说明为什么在没有得到期望的情况下期望得到期望的结果,并根据文档说明理由,那么您只是要求我们用定制的教程重写另一个演示文稿,不知道您的误解是什么
  • 你的问题毫无意义。前两个查询不同,因为它们使用不同的表。
  • @SamuelLiew 您刚刚重新打开了它,但它不应该打开。请参阅我的最后一条评论(说我的预编辑 cmets 仍然适用)。没有版本说明为什么 Oracle (+) 符号代码会返回与关键字代码相同的代码,所以它只是要求我们重写该文档,再次被误解,不知道他们的误解是什么,所以我们无法解决他们。 (非提问者 oramas 的编辑实际上错误地删除了提问者对他们如何解析关键字代码的有用描述。)没有minimal reproducible example,因为这并没有说明为什么输出会相同。

标签: sql oracle join


【解决方案1】:

不,顺序无关紧要。优化器决定表连接的顺序。

对您的问题的简短回答是:优化器使用将尽快返回结果的顺序,通常它会选择最佳选项。详细的答案会更长。

您可以通过使用提示来指示 Oracle 使用特定的顺序。对于此查询,您的假设是正确的:

SELECT /*+ ORDERED */ first_name, last_name, department_name, city, postal_code, street_address, country_id
FROM employees e 
   JOIN departments d ON (e.department_id = d.department_id)
   JOIN locations l USING (location_id)
   JOIN COUNTRIES USING (country_id);

或者您可以使用LEADING 提示:

SELECT /*+ LEADING(e d l c) */ first_name, last_name, department_name, city, postal_code, street_address, country_id
FROM employees e 
   JOIN COUNTRIES c USING (country_id)
   JOIN locations l USING (location_id)
   JOIN departments d ON (e.department_id = d.department_id);

【讨论】:

  • 感谢您的回复。但是,我相信这不会改变返回的结果。我更新了我的问题以便更好地理解,请您再次检查一下吗?
猜你喜欢
  • 1970-01-01
  • 2017-11-15
  • 2019-03-23
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-06
相关资源
最近更新 更多