笛卡尔乘积 :
当一个连接条件无效或被遗漏时,其结果是一个笛卡尔乘积 (Cartesian product),其中所有行的组合都被显示。第一个表中的所有行连接到第二个表中的所有行。一个笛卡尔乘积会产生大量的行,其结果没有什么用。你应该在 WHERE 子句中始终包含一个有效的连接条件,除非你有特殊的需求,需要从所有表中组合所有的行。
多表查询分类
等值连接
为了确定一个雇员的部门名,需要比较 EMPLOYEES 表中的 DEPARTMENT_ID 列与DEPARTMENTS 表中的 DEPARTMENT_ID 列的值。在 EMPLOYEES 和DEPARTMENTS 表之间的关系是一个相等 (equijoin) 关系,即,两 个 表 中DEPARTMENT_ID 列的值必须相等。
等值连接特点:
注意:
等值连接也被称为简单连接 (simple joins) 或内连接 (inner joins)。
等值连接的使用
SELECT 子句指定要返回的列名:
− employee last name、employee number 和 department number,这些是
EMPLOYEES 表中的列
− department number、department name 和 location ID,这些
是 DEPARTMENTS 表中的列
− EMPLOYEES 表
− DEPARTMENTS 表
WHERE 子句指定表怎样被连接:
EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.DEPARTMENT_ID,因为 DEPARTMENT_ID 列是两个表的同名列,它必须用表名做前缀以避免混淆。
增加搜索条件
添加查询条件
除连接之外,可能还要求用 WHERE 子句在连接中限制一个或多个表中的行。
限制不能缺的列
限制不明确的列名
使用表别名
表别名定义原则
多表连接
示例一:
查询雇员 King 所在的部门名称。
select d.department_name from employees e,departments d where e.dept_id = d.department_id and e.last_name = 'King';
示例二:
显示每个雇员的 last name、departmentname 和 city。
SELECT e.last_name, d.department_name, l.city
FROM employees e, departments d, locations l
WHERE e.department_id = d.department_id
AND d.location_id = l.location_id;
非等值连接
一个非等值连接是一种不同于等值操作的连接条件。 EMPLOYEES 表 和JOB_GRADES A 表之间的关系有一个非等值连接例子。在两个表之间的关系是EMPLOYEES 表中的 SALARY 列必须是 JOB_GRADES 表的 LOWEST_SALARY 和HIGHEST_SALARY 列之间的值。使用不同于等于 (=) 的操作符获得关系。
示例一:
创建 job_grades 表,包含 lowest_sal ,highest_sal ,grade_level。
create table job_grades(lowest_sal int,highest_sal int ,grade_level varchar(30));
示例二:
插入数据
1000 2999 A 2000 4999 B 5000 7999 C 8000 12000 D
insert into job_grades values(1000,2999,'A');
insert into job_grades values(2000,4999,'B');
insert into job_grades values(5000,7999,'C');
insert into job_grades values(8000,12000,'D');
示例三:
查询所有雇员的薪水级别。
select e.last_name,j.grade_level from employees e ,job_grades j where e.salary between j.lowest_sal and j.highest_sal;
自连接
连接一个表到它自己。有时需要连接一个表到它自己。为了找到每个雇员的经理的名字,则需要连接EMPLOYEES 表到它自己,或执行一个自连接。
图片中的例子连接 EMPLOYEES 表到它自己。为了在 FROM 子句中模拟两个表,对于相同的表 EMPLOYEES,用两个别名,分别为 worker 和 manager。在该例中,WHERE 子句包含的连接意味着 “一个工人的经理号匹配该经理的雇员号”。
示例一:
查询每个雇员的经理的名字以及雇员的名字,雇员名字列别名为W,经理列别名为M。
SELECT
worker.LAST_NAME W,manager.LAST_NAME M
from employees worker,employees manager
where worker.MANAGER_ID = manager.EMPLOYEE_ID;
示例二:
查询Fox的经理是谁?显示他的名字。
SELECT
worker.LAST_NAME,manager.LAST_NAME
from employees worker,employees manager
where worker.MANAGER_ID = manager.EMPLOYEE_ID
AND
worker.LAST_NAME = 'Fox';