从多个表中获取数据

从多个表中获取数据


显示来自多个表的数据

大型数据库的相关表通过使用外键和主键或通常称为公共列的内容进行链接。连接表的能力将使您能够为生成的结果表添加更多含义。对于要在查询中联接的“n”个数字表,最少 (n-1) 个联接条件是必需的。Oracle 根据连接条件将匹配的行组合起来,并显示满足连接条件的行。

联接分类如下

  • 自然连接(也称为等值连接或简单连接)- 通过使用通用命名和定义的列创建连接。

  • 非等式联接 – 当要联接的表中没有等效行时联接表 – 例如,将表的一列中的值与另一表中的一系列值进行匹配。

  • 自联接 – 将表与自身联接。

  • 外连接 – 当另一个表中没有匹配的记录时,在输出中包括一个表的记录。

  • 笛卡尔连接(也称为笛卡尔积或交叉连接)- 将第一个表中的每一行复制到第二个表中的每一行。通过显示每个可能的记录组合在表之间创建连接。

自然连接

NATURAL 关键字可以简化 equijoin 的语法。只要两个(或更多)表具有相同名称的列,并且这些列是连接兼容的,即列具有共享的值域,就可以使用 NATURAL JOIN。连接操作连接表中具有相同命名列的相同列值的行。

考虑 DEPARTMENTS 和 EMPLOYEES 表之间的一对多关系。每个表都有一个名为 DEPARTMENT_ID 的列。该列是 DEPARTMENTS 表的主键和 EMPLOYEES 表的外键。

SELECT E.first_name NAME,D.department_name DNAME
FROM employees E NATURAL JOIN departments D;

FIRST_NAME DNAME
---------- ------
MILLER     DEPT 1
JOHN       DEPT 1
MARTIN     DEPT 2
EDWIN      DEPT 2

下面的 SELECT 查询通过使用 ON 关键字显式指定连接条件来连接两个表。

SELECT E.first_name NAME,D.department_name DNAME
FROM employees E JOIN departments D
ON (E.department_id = D.department_id);

关于 NATURAL JOIN 有一些限制。不能使用 NATURAL JOIN 指定 LOB 列。此外,连接中涉及的列不能由表名或别名限定。

使用条款

使用自然连接,Oracle 隐式标识列以构成连接的基础。许多情况需要显式声明连接条件。在这种情况下,我们使用 USING 子句来指定连接标准。由于 USING 子句基于列的相等性连接表,因此它也称为 Equijoin。它们也称为内部联接或简单联接。

句法:

SELECT <column list>
FROM   TABLE1   JOIN   TABLE2	
USING (column name)

考虑下面的 SELECT 查询,EMPLOYEES 表和 DEPARTMENTS 表使用公共列 DEPARTMENT_ID 连接。

SELECT E.first_name NAME,D.department_name DNAME
FROM employees E JOIN departments D
USING (department_id);

自加入

当存储在单个表中的行之间存在感兴趣的关系时,SELF-JOIN 操作会生成一个结果表。换句话说,当一个表与自身连接时,连接被称为自连接。

考虑 EMPLOYEES 表,其中包含员工及其报告经理。要查找员工的经理姓名需要对 EMP 表本身进行联接。这是自加入的典型候选者。

SELECT e1.FirstName Manager,e2.FirstName Employee
FROM employees e1 JOIN employees e2
ON (e1.employee_id = e2.manager_id)
ORDER BY e2.manager_id DESC;

非等值连接

当相关列不能用等号连接时使用非等式连接 – 这意味着要连接的表中没有等效行。非等式连接使您可以将范围的最小值存储在一列中记录和另一列中的最大值。因此,您可以使用非等式连接来确定要运送的物品是否在列中的最小和最大范围之间,而不是查找列到列的匹配项。如果连接确实找到了该物品的匹配范围,则相应的运输费用可以在结果中退还。与传统的等式连接方法一样,可以在 WHERE 子句中执行非等式连接。此外,JOIN 关键字可与 ON 子句一起使用以指定连接的相关列。

SELECT E.first_name,
            J.job_hisal,
            J.job_losal,
            E.salary
     FROM employees E JOIN job_sal J
     ON (E.salary BETWEEN J.job_losal AND J.job_losal);

我们可以使用前面讨论过的所有比较参数,如相等和不等运算符、BETWEEN、IS NULL、IS NOT NULL 和 RELATIONAL。

外连接

外部联接用于识别一个表中的行与第二个表中的行不匹配的情况,即使这两个表是相关的。

外部联接分为三种类型:LEFT、RIGHT 和 FULL OUTER JOIN。它们都以 INNER JOIN 开始,然后将一些已删除的行重新添加回去。LEFT OUTER JOIN 将在连接条件中从第一个(左)表中删除的所有行添加回来,并且第二个(右)表中的输出列设置为 NULL。RIGHT OUTER JOIN 将在连接条件中从第二个(右)表中删除的所有行添加回来,并且第一个(左)表中的输出列设置为 NULL。FULL OUTER JOIN 重新添加从两个表中删除的所有行。

右外连接

RIGHT OUTER JOIN 将在连接条件中从第二个(右)表中删除的所有行添加回来,并且第一个(左)表中的输出列设置为 NULL。请注意以下查询列出了员工及其相应的部门。也没有员工被分配到部门 30。

SELECT E.first_name, E.salary, D.department_id          
FROM employees E, departments D
WHERE E.DEPARTMENT_ID (+) = D.DEPARTMENT_ID;

FIRST_NAME SALARY     DEPARTMENT_ID
---------- ---------- ----------
JOHN       6000       10
EDWIN      2000       20
MILLER     2500       10
MARTIN     4000       20
                      30

左外连接

LEFT OUTER JOIN 将在连接条件中从第一个(左)表中删除的所有行添加回来,并且第二个(右)表中的输出列设置为 NULL。上面演示的查询可用于演示左外连接,通过交换 (+) 符号的位置。

SELECT E.first_name, E.salary, D.department_id
FROM employees E, departments D
WHERE   D.DEPARTMENT_ID = E.DEPARTMENT_ID (+);

FIRST_NAME SALARY     DEPARTMENT_ID
---------- ---------- ----------
JOHN       6000       10
EDWIN      2000       20
MILLER     2500       10
MARTIN     4000       20
                      30

全外连接

FULL OUTER JOIN 重新添加从两个表中删除的所有行。下面的查询显示了员工及其部门的列表。请注意,到目前为止,员工 ‘MAN’ 尚未分配任何部门(为 NULL),部门 30 未分配给任何员工。

SELECT  nvl (e.first_name,'-') first_name, nvl (to_char (d.department_id),'-') department_id
FROM employee e FULL OUTER JOIN department d
ON e. depARTMENT_ID = d. depARTMENT_ID;

FIRST_NAME DEPARTMENT_ID
---------- --------------------
MAN        -
JOHN       10
EDWIN      20
MILLER     10
MARTIN     20
-          30

6 rows selected.

笛卡尔积或交叉连接

对于两个实体 A 和 B,A * B 称为笛卡尔积。笛卡尔积由每个表中行的所有可能组合组成。因此,当一个10行的表和一个20行的表连接时,笛卡尔积是200行(10 * 20 = 200)。 比如连接8行的employee表和3行的department表会产生一个 24 行的笛卡尔积表 (8 * 3 = 24)。

交叉连接是指两个表的笛卡尔积。它产生两个表的叉积。可以使用 CROSS JOIN 子句编写上述查询。

笛卡尔积结果表通常不是很有用。事实上,这样的结果表可能会产生极大的误导。如果您对 EMPLOYEES 和 DEPARTMENTS 表执行以下查询,结果表意味着每个员工与每个部门都有关系,我们知道事实并非如此!

SELECT E.first_name, D.DNAME
FROM employees E,departments D;

交叉连接可以写成,

SELECT E.first_name, D.DNAME
FROM employees E CROSS JOIN departments D;

觉得文章有用?

点个广告表达一下你的爱意吧 !😁