Oracle DB使用连接显示多个表中的数据(五)

2014-11-24 16:56:23 · 作者: · 浏览: 2
old的雇员编号为103,因此Hunold是Lorentz 的经理。
在这一过程中,对表进行了两次搜索。第一次是在表中LAST_NAME列中查找Lorentz,得知其MANAGER_ID值为103。第二次是搜索EMPLOYEE_ID列以查找103,然后在LAST_NAME列中找到了Hunold。
使用ON子句进行自联接
SELECT worker.last_name emp, manager.last_name mgr FROM employees worker JOIN employees manager
ON (worker.manager_id = manager.employee_id);
ON子句还可以用于联接同一表内或者不同表中具有不同名称的列。
所示示例为EMPLOYEES表基于EMPLOYEE_ID和MANAGER_ID列进行自联接。
注:示例所示的联接列(e.manager_id = m.employee_id)两边的圆括号是可选的。因此,即便是ON e.manager_id = m.employee_id效果也一样。
非等值联接
非等值联接是一个包含非等号运算符的联接条件。
EMPLOYEES表和JOB_GRADES表之间的关系就是一个非等值联接的示例。EMPLOYEES表中的SALARY列的范围介于JOB_GRADES表的LOWEST_SAL和HIGHEST_SAL列中的值之间。因此,可以根据每位雇员的薪金划分其等级。通过使用等号(=) 以外的运算符可以实现这一关系。
使用非等值联接检索记录
SELECT e.last_name, e.salary, j.grade_level FROM employees e JOIN job_grades j ON e.salary BETWEEN j.lowest_sal AND j.highest_sal;
示例中创建了一个非等值联接来评估雇员的薪金等级。薪金必须介于任何一对最低薪金和最高薪金之间。
值得注意的是,在执行这一查询时,所有雇员只能出现一次。雇员不能在列表中重复出现。
这有以下两个原因:
JOB_GRADES表中的任何一行都不包含重叠的等级。也就是说,每位雇员的薪金值只能介于薪金等级表中某一行的最低薪金值和最高薪金值之间。
所有雇员的薪金都在职务等级表提供的限额之内。也就是说,任何雇员的薪金都不低于LOWEST_SAL列中的最低值,也不高于HIGHEST_SAL列中的最高值。
注:可以使用其它条件,如<=和>=,但最简单的方法是使用BETWEEN。请记住,在使用BETWEEN条件时,应先指定最低值,后指定最高值。Oracle Server 将BETWEEN条件解释为一对AND条件。因此,使用BETWEEN没有性能优势,只是为了简化逻辑才使用它。
示例中指定了表别名,这是考虑到性能原因,而不是因为可能出现的混淆。
使用OUTER联接返回没有直接匹配的记录
如果某一行不满足联接条件,则查询结果中就不会出现该行。
针对EMPLOYEES和DEPARTMENTS表使用简单等值联接来返回右侧的结果。结果集不包含以下内容:
部门ID 190,因为EMPLOYEES表中不存在具有该部门ID 的雇员
姓氏为Grant 的雇员,因为没有为该雇员分配部门ID
要返回没有任何雇员部门记录,或者返回没有分配部门的雇员,您可以使用OUTER联接。
INNER联接与OUTER联接
在SQL:1999 中,如果两个表的联接只返回相匹配的行,则称该联接为INNER联接。
如果两个表之间的联接不仅返回INNER联接的结果,还返回左(或右)表中不匹配的行,则称该联接为左(或右)OUTER联接。
如果两个表之间的联接不仅返回INNER联接的结果,还返回左和右联接的结果,则称该联接为完全OUTER联接。
使用NATURAL JOIN、USING或ON子句对表进行联接时会生成INNER联接。输出中不会显示任何不匹配的行。要返回不匹配的行,可以使用OUTER联接。OUTER联接将返回满足联接条件的所有行,还会返回一个表在另一表中没有满足联接条件的对应行的部分或全部行。
有三种OUTER联接类型:
LEFT OUTER
RIGHT OUTER
FULL OUTER
LEFT OUTER JOIN
SELECT e.last_name, e.department_id, d.department_name FROM employees e LEFT OUTER JOIN departments d ON (e.department_id = d.department_id) ;
此查询将检索EMPLOYEES表(它是左表)中的所有行,即使DEPARTMENTS表中没有匹配项也是如此。
RIGHT OUTER JOIN
SELECT e.last_name, d.department_id, d.department_name FROM employees e RIGHT OUTER JOIN departments d ON (e.department_id = d.department_id);
此查询将检索DEPARTMENTS表(它是右表)中的所有行,即使EMPLOYEES表中没有匹配项也是如此。
FULL OUTER JOIN
SELECT e.last_name, d.department_id, d.department_name FROM employees e FULL OUTER JOIN departments d ON (e.department_id = d.department_id) ;
此查询将检索EMPLOYEES表中的所有行,即使DEPARTMENTS表中没有匹配项也是如此。它还检索DEPARTMENTS表中的所有行,即使EMPLOYEES表中没有匹配项也是如此。
笛卡尔积
出现以下情况时将形成笛卡尔积:
– 联接条件被忽略
– 联接条件无效
– 第一个表中的所有行被联接到第二个表中的所有行
如果要避免生成笛卡尔积,请始终包括有效的联接条件。
当一个联接条件无效或被完全忽略时,就会生成笛卡尔积。此时会显示行的所有组合。第一个表中的所有行会被联接到第二个表中的所有行。
笛卡尔积往往会生成大量的行,这种结果几乎没有任何用处。因此,应始终包括有效的联接条件,除非有特定需求需要组合所有表中的所有行。
如果某些测试需要生成大量的行来模拟合理的数据量,则笛卡尔积非常有用。
生成笛卡尔积
如果某个联接条件被忽略,则会生成笛卡尔积。由于没有指定联接条件,EMPLOYEES表中的所有行(20 行)与DEPARTMENTS表中的所有行(8 行)联接在一起,因此在输出中生成了160 行。
创建交叉联接
CROSS JOIN子句可生成两个表的叉积。
这也称为两个表间的笛卡尔积。
SELECT last_name, depart