NATURAL JOIN和USING子句的意外结果

jbo*_*one 3 sql database oracle

所以我正在学习从多个表中获取数据,我有一个关于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)
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

Cai*_*ard 5

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

如果您检查USING表单,您会看到每个表中的manager_id是不同的.(提出您的疑问SELECT *,你会看到..)

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

值得注意的是,应该很少使用自然连接和使用.当然要了解它们以便你能够理解它们的存在,但是你应该坚持使用常规的显式连接,以保持一致和清晰的行为 - 如果将来升级应用程序并在这两个表中添加两个新列,命名相同但NJ将会失败的不同数据.

编辑:

运行这个:

SELECT *
FROM employees JOIN departments
USING (department_id)
WHERE department_id = 80
ORDER BY location_id desc;
Run Code Online (Sandbox Code Playgroud)

查看显示经理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;
Run Code Online (Sandbox Code Playgroud)

on e.department_id = d.department_id AND e.manager_id = d.manager_id不是为zlotkey行真

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

  • 看起来更像是一个精明的观察,而不是讨厌我 (2认同)