首页 > 解决方案 > NATURAL JOIN 和 USING 子句的意外结果

问题描述

所以我正在学习如何从多个表中获取数据,并且我对 NATURAL JOIN 和 USING 子句有疑问。所以我有 2 个要从中提取数据的表;员工和部门。

SQL> describe employees 
Name                                      Null?    Type
 ----------------------------------------- -------- ------------------------
 EMPLOYEE_ID                                        NUMBER(6)
 FIRST_NAME                                         VARCHAR2(20)
 LAST_NAME                                 NOT NULL VARCHAR2(25)
 EMAIL                                     NOT NULL VARCHAR2(25)
 PHONE_NUMBER                                       VARCHAR2(20)
 HIRE_DATE                                 NOT NULL DATE
 JOB_ID                                    NOT NULL VARCHAR2(10)
 SALARY                                             NUMBER(8,2)
 COMMISSION_PCT                                     NUMBER(2,2)
 MANAGER_ID                                         NUMBER(6)
 DEPARTMENT_ID                                      NUMBER(4)

SQL> describe departments
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------------------
 DEPARTMENT_ID                             NOT NULL NUMBER(4)
 DEPARTMENT_NAME                                    VARCHAR2(30)
 MANAGER_ID                                         NUMBER(6)
 LOCATION_ID                                        NUMBER(4)

当我在两个不同的表达式中使用 NATURAL JOIN 和 USING 时,我有两个不同的输出。我知道 USING 专门匹配两个表中的一列,但这对输出有何影响?与 NATURAL JOIN 相比,使用 USING 的表达式为什么会产生一个额外的值?

SELECT department_id, manager_id, last_name, location_id
FROM employees NATURAL JOIN departments
WHERE department_id = 80
ORDER BY location_id desc;

DEPARTMENT_ID MANAGER_ID LAST_NAME                 LOCATION_ID
------------- ---------- ------------------------- -----------
       80        149 Abel                             2500
       80        149 Grant                            2500
       80        149 Taylor                           2500

SELECT department_id, departments.manager_id, last_name, location_id
FROM employees JOIN departments
USING (department_id)
WHERE department_id = 80
ORDER BY location_id desc;

DEPARTMENT_ID MANAGER_ID LAST_NAME                 LOCATION_ID
------------- ---------- ------------------------- -----------
       80        149 Zlotkey                         2500 <-Additional Line*
       80        149 Grant                           2500
       80        149 Taylor                          2500
       80        149 Abel                            2500

任何帮助和建议表示赞赏!

标签: sqldatabaseoracle

解决方案


因为 NATURAL JOIN 连接所有具有相同名称的列,因此您的 NJ 查询也将连接 manager_id,而 USING 表单不会

如果您检查 USING 表单,您会发现每个表中的 manager_id 是不同的。(进行查询SELECT *,您会看到..)

当自然加入这两个表之间的 manager_id 差异时,将从结果中删除该行

可能值得注意的是,自然连接和使用应该很少使用。一定要了解它们,这样你才能欣赏它们的存在,但你应该坚持使用常规的显式连接,以保持一致和清晰的行为 - 如果应用程序将来升级并且两个新列添加到这两个表中,命名相同但不同的数据新泽西州会失败。

编辑:

运行这个:

SELECT *
FROM employees JOIN departments
USING (department_id)
WHERE department_id = 80
ORDER BY location_id desc;

查看显示经理 ID 的两列。Zlotkey 行上的数据会有所不同

你自然加入有效地做到了这一点:

SELECT *
FROM employees e JOIN departments d
on e.department_id = d.department_id AND e.manager_id = d.manager_id
WHERE department_id = 80
ORDER BY location_id desc;

并且on e.department_id = d.department_id AND e.manager_id = d.manager_id对于 zlotkey 行不正确

这就是自然连接有风险并且可能无用的原因——仅仅因为两列具有相同的名称并不意味着它们中的数据是相关的。事实上,在你的情况下,你的部门有经理,你的员工有经理。我的工作中也有这种设置,但是我的经理不是我所在部门的经理


推荐阅读