当查询的数据并不是来源于一个表时, 需要使用夺标链接操作完成查询, 根据不同表中数据之间的关系查询相关联的数据.
连接两个表, 通过相等或不等判断链接列, 成为内连接. 在内连接中典型的连接运算有=或<>之类的比较运算符, 包括等值连接和自然连接
在两个表之间的连接, 返回内连接的结果, 同时返回不匹配行的左或右表的连接, 称为左(或右)连接. 返回内连接的结果, 同时返回左或右连接, 称为全外连接.
当一个查询是另一个查询的条件时, 称为子查询
笛卡尔乘积是指在数学中, 两个集合X和Y的笛卡尔乘积(Cartesian product), 又称直积. 表示为X*Y, 第一个对象时X的成员而第二个对象是Y的所有可能有序对的其中一个成员
当一个连接条件无效或被遗漏时, 其结果是一个笛卡尔乘积, 所有行的组合都会被显示. 第一个表中的所有行连接到第二个表中所有行. 一个笛卡尔乘积会产生大量的行, 其结果没有什么用. 应该在WHERE字句中始终包含一个有效的连接条件.
使用一个连接从多个表中查询数据
select table1.column, table2.column
from table1, table2
where table1.column1 = table2.column2 -- 注意, 如果没有连接条件, 会产生笛卡尔乘积
等值连接也被称为简单连接或内连接. 是通过等号来判断连接条件中的数据值是否相匹配
示例一: 查询所有雇员名字以及他们所在的部门名称
SQL> select last_name, department_name
2 from employees, departments
3 where employees.department_id = departments.department_id;
LAST_NAME DEPARTMENT_NAME
------------------------- ------------------------------
Whalen Administration
Fay Marketing
Hartstein Marketing
Tobias Purchasing
示例二: 显示名字为Taylor的雇员的名字和部门号
SQL> select last_name, employees.department_id
2 from employees, departments
3 where employees.department_id = departments.department_id
4 and employees.last_name='Taylor';
LAST_NAME DEPARTMENT_ID
------------------------- -------------
Taylor 80
Taylor 50
可以使用表的别名代替表名, 就像列别名给列起另一个别名一样. 别名有助于保持代码较小, 因此, 使用的存储器也少.
示例: 显示Taylor的名字和部门名
SELECT
e.last_name,
d.department_name
FROM
employees e,
departments d
WHERE
d.DEPARTMENT_ID = e.DEPARTMENT_ID;
为了连接n个表, 你最少需要n-1个连接条件. 例如, 为了连接3个表, 你最少需要两个连接条件
示例一: 查询每个雇员的last_name, department_name, city( city 来源于 locations 表);
SQL> select e.last_name, d.department_name, l.city
2 from employees e, departments d, locations l
3 where e.department_id = d.department_id
4 and d.location_id = l.location_id;
LAST_NAME DEPARTMENT_NAME CITY
------------------------- ------------------------------ ------------------------------
Abel Sales Oxford
Ande Sales Oxford
Atkinson Shipping South San Francisco
Austin IT Southlake
Baer Public Relations Munich
示例二: 查询Taylor的雇员ID, 部门名称, 和工作的城市
SQL> select e.employee_id, d.department_id, l.city
2 from employees e, departments d, locations l
3 where e.department_id = d.department_id
4 and d.location_id = l.location_id
5 and e.last_name = 'Taylor';
EMPLOYEE_ID DEPARTMENT_ID CITY
----------- ------------- ------------------------------
176 80 Oxford
180 50 South San Francisco
非等值连接是一种不使用相等作为连接条件的连接查询, 如!=, <, >, >=, <=, BETWEEN AND, 等都是非等值连接的条件判断.
先准备一个工资等级的表
SQL> create table JOB_GRADES(
2 lowest_sal number,
3 highest_sal number,
4 gra varchar2(10)
5 );
加一些数据
LOWEST_SAL HIGHEST_SAL GRA
---------- ----------- ----------
1000 2999 A
3000 5999 B
6000 9999 C
10000 14999 D
15000 24999 E
25000 40000 F
我们利用此表来学习非等值连接
示例: 查询所有员工的工资等级
SQL> select e.last_name, e.salary, g.gra from employees e, job_grades g where e.salary between g.lowest_sal and g.highest_sal;
LAST_NAME SALARY GRA
------------------------- ---------- ----------
Olson 2100.00 A
Markle 2200.00 A
Philtanker 2200.00 A
Landry 2400.00 A
Gee 2400.00 A
Colmenares 2500.00 A
自连接是一个表连接其自身的操作
示例: 查询每个雇员的经理的名字
SQL> select e1.last_name, e2.last_name from employees e1, employees e2 where e1.manager_id = e2.employee_id;
LAST_NAME LAST_NAME
------------------------- -------------------------
Smith Cambrault
Ozer Cambrault
Kumar Cambrault
Fox Cambrault
Bloom Cambrault
Bates Cambrault
外连接是查询出符合连接条件的数据同时还包含孤儿数据. 左外连接包含左表的孤儿数据, 右外连接包含右表的孤儿数据
孤儿数据是指被连接的列的值为空的数据
左外连接(LEFT OUTER JOIN): 包含左表的孤儿数据
右外连接(RIGHT OUTER JOIN): 包含右表的孤儿数据
全外连接(FULL OUTER JOIN): 包含两个表中的孤儿数据
用LEFT OUTER JOIN | RIGHT OUTER JOIN | FULL OUTER JOIN定义连接类型, 用ON字句创建连接条件
示例: 用左外连接查询雇员名字以及他们所在的部门名称, 包含那些没有部门的雇员
SQL> select e.last_name, d.department_name
2 from employees e
3 left outer join departments d
4 on e.department_id = d.department_id;
LAST_NAME DEPARTMENT_NAME
------------------------- ------------------------------
Whalen Administration
Fay Marketing
Hartstein Marketing
Colmenares Purchasing
Gietz Accounting
Higgins Accounting
Grant
示例: 用右外连接查询雇员名以及他们所在部门的名称, 包括没有雇员的部门
SQL> select e.last_name, d.department_name
2 from employees e
3 right outer join departments d
4 on e.department_id = d.department_id;
LAST_NAME DEPARTMENT_NAME
------------------------- ------------------------------
Whalen Administration
Fay Marketing
Hartstein Marketing
Gietz Accounting
Higgins Accounting
Treasury
Corporate Tax
Control And Credit
示例: 查询所有雇员和部门, 包含那些没有没有部门的雇员以及没有雇员的部门
SQL> select e.last_name, d.department_name
2 from employees e
3 full outer join departments d
4 on e.department_id = d.department_id;
LAST_NAME DEPARTMENT_NAME
------------------------- ------------------------------
Livingston Sales
Grant
Johnson Sales
Taylor Shipping
NOC
Manufacturing
Government Sales
IT Support
Benefits
Shareholder Services
Retail Sales
在Oracle数据库中对外连接中的左外和右外连接做了扩展, 可以简化外连接的语法. 通过在连接条件的后侧使用(+)来表示是否显示孤儿数据, 有(+)表示不显示孤儿数据, 而另一侧则显示孤儿数据. 但是该种写法仅在Oracle数据库中有效
示例一: 查询雇员名字以及他们所在部门名称, 包含那些没有雇员的部门.
SQL> select e.last_name, d.department_name
2 from employees e, departments d
3 where e.department_id(+) = d.department_id;
LAST_NAME DEPARTMENT_NAME
------------------------- ------------------------------
Whalen Administration
Fay Marketing
Hartstein Marketing
Gietz Accounting
Higgins Accounting
Treasury
Corporate Tax
Control And Credit
示例二: 用左外连接查询雇员名字以及他们所在的部门名称, 包含那些没有部门的雇员
LAST_NAME DEPARTMENT_NAME
------------------------- ------------------------------
Whalen Administration
Fay Marketing
Hartstein Marketing
Gietz Accounting
Higgins Accounting
Treasury
Corporate Tax
Control And Credit
示例: 查询Employee表和departments的笛卡尔乘积
SQL> select employee_id, department_name
2 from employees
3 cross join departments;
EMPLOYEE_ID DEPARTMENT_NAME
----------- ------------------------------
202 Payroll
203 Payroll
204 Payroll
205 Payroll
206 Payroll
2889 rows selected
示例: 查询部门ID, 部门名以及他们所在的城市
SQL> select d.department_id, d.department_name, l.city
2 from departments d
3 natural join locations l;
这个句子等同于等值连接如下
SQL> select d.department_id, d.department_name, l.city
2 from departments d, locations l
3 where d.location_id = l.location_id;
示例:
查询location_id为1800的部门名称以及他们所在的城市名称, 指定location_id为连接列
SQL> select d.department_name, l.city
2 from departments d
3 join locations l
4 using(location_id)
5 where location_id = 1800;
DEPARTMENT_NAME CITY
------------------------------ ------------------------------
Marketing Toronto
内连接(INNER JOIN): 内连接通过INNER JOIN来建立两个表的连接. 在内连接中使用INNER JOIN作为表的连接, 用ON字句给定绑定条件, INNER JOIN 语句在性能上和其他语句并没有什么优势
示例: 查询雇员id为202的雇员名字, 部门名称, 以及工作的成时
SQL> select e.last_name, d.department_name, l.city
2 from employees e
3 inner join departments d
4 on e.department_id = d.department_id
5 inner join locations l
6 on l.location_id = d.location_id
7 where e.employee_id = 202;
LAST_NAME DEPARTMENT_NAME CITY
------------------------- ------------------------------ ------------------------------
Fay Marketing Toronto
可以把on的连接条件换成using字句
SQL> select e.last_name, d.department_name, l.city
2 from employees e
3 inner join departments d
4 using(department_id)
5 inner join locations l
6 using(location_id)
7 where e.employee_id = 202;
LAST_NAME DEPARTMENT_NAME CITY
------------------------- ------------------------------ ------------------------------
Fay Marketing Toronto