Mysql联结表

一、关系表

假如有一个包含产品目录的数据库表,其中每种类别的物品占一行。 对于每种物品要存储的信息包括产品描述和价格,以及生产该产品的供 应商信息。现在,假如有由同一供应商生产的多种物品,那么在何处存储供应 商信息(如,供应商名、地址、联系方法等)呢?将这些数据与产品信 息分开存储的理由如下。

  • 因为同一供应商生产的每个产品的供应商信息都是相同的,对每 个产品重复此信息既浪费时间又浪费存储空间。
  • 如果供应商信息改变(例如,供应商搬家或电话号码变动),只需 改动一次即可。
  • 如果有重复数据(即每种产品都存储供应商信息),很难保证每次 输入该数据的方式都相同。不一致的数据在报表中很难利用。

关键是,相同数据出现多次决不是一件好事,此因素是关系数据库 设计的基础。关系表的设计就是要保证把信息分解成多个表,一类数据 一个表。各表通过某些常用的值(即关系设计中的关系(relational))互 相关联。

在这个例子中,可建立两个表,一个存储供应商信息,另一个存储 产品信息。vendors表包含所有供应商信息,每个供应商占一行,每个供 应商具有唯一的标识。此标识称为主键(primary key),可以是供应商ID或任何其他唯一值。
products表只存储产品信息,它除了存储供应商ID(vendors表的主 键)外不存储其他供应商信息。vendors表的主键又叫作products的外键, 它将vendors表与products表关联,利用供应商ID能从vendors表中找出 相应供应商的详细信息。

外键(foreignkey)

外键为某个表中的一列,它包含另一个表 的主键值,定义了两个表之间的关系。

这样做的好处如下:

  • 供应商信息不重复,从而不浪费时间和空间;
  • 如果供应商信息变动,可以只更新vendors表中的单个记录,相关表中的数据不用改动;
  • 由于数据无重复,显然数据是一致的,这使得处理数据更简单。

总之,关系数据可以有效地存储和方便地处理。因此,关系数据库 的可伸缩性远比非关系数据库要好。
可伸缩性(scale) 能够适应不断增加的工作量而不失败。设 计良好的数据库或应用程序称之为可伸缩性好

​ ——《Mysql必知必会》

二、创建联结

方法:规定要联结的所有表,以及他们之间如何来联结

只需要通过一条select语句就可以把存储在多个表中的数据检索出来

例子:查看所有员工的职业,部门和薪资

mysql> select ename,job ,dname ,sal 
       from emp,dept 
       where emp.deptno = dept.deptno order by job;
+--------+-----------+------------+---------+
| ename  | job       | dname      | sal     |
+--------+-----------+------------+---------+
| SCOTT  | ANALYST   | RESEARCH   | 3000.00 |
| FORD   | ANALYST   | RESEARCH   | 3000.00 |
| SMITH  | CLERK     | RESEARCH   |  800.00 |
| ADAMS  | CLERK     | RESEARCH   | 1100.00 |
| JAMES  | CLERK     | SALES      |  950.00 |
| MILLER | CLERK     | ACCOUNTING | 1300.00 |
| JONES  | MANAGER   | RESEARCH   | 2975.00 |
| BLAKE  | MANAGER   | SALES      | 2850.00 |
| CLARK  | MANAGER   | ACCOUNTING | 2450.00 |
| KING   | PRESIDENT | ACCOUNTING | 5000.00 |
| ALLEN  | SALESMAN  | SALES      | 1600.00 |
| WARD   | SALESMAN  | SALES      | 1250.00 |
| MARTIN | SALESMAN  | SALES      | 1250.00 |
| TURNER | SALESMAN  | SALES      | 1500.00 |
+--------+-----------+------------+---------+
14 rows in set (0.00 sec)

分析:

FROM子句:

  • 这里的from子句指出了要联结的所有表的名称。

WHERE子句:

  • where指出了联结规则

三、联结表时WHERE子句不能丢

到这里我们明白多个表之间的联结是同通过WHERE子句的联结规则来连接的,但是这种链接规则是在SELECT语句执行过程中才连接的,并不是在创建表的的时候就强调他们之间有这种关系,而是必须通过WHERE子句来表达你想达到的目的。

当然了,丢掉这个where子句在sql语法上并没有毛病,但是没有按照约束规则来达成你逻辑上某些列的匹配。

笛卡尔积:

由于没有通过where子句来规定联结关系,那么返回结果将是一个笛卡尔积数目的表。
返 回 表 总 行 数 = 表 1 行 数 × 表 2 行 数 × 表 3 行 数 × . . . × 表 n 行 数 返回表总行数 = 表1行数 × 表2行数 ×表3行数×...×表n行数 返回表总行数=表1行数×表2行数×表3行数×...×表n行数

mysql> select ename,job ,dname ,sal 
       from emp,dept  
       order by ename;
+--------+-----------+------------+---------+
| ename  | job       | dname      | sal     |
+--------+-----------+------------+---------+
| ADAMS  | CLERK     | OPERATIONS | 1100.00 |
| ADAMS  | CLERK     | SALES      | 1100.00 |
| ADAMS  | CLERK     | RESEARCH   | 1100.00 |
| ADAMS  | CLERK     | ACCOUNTING | 1100.00 |
| ALLEN  | SALESMAN  | OPERATIONS | 1600.00 |
| ALLEN  | SALESMAN  | SALES      | 1600.00 |
| ALLEN  | SALESMAN  | RESEARCH   | 1600.00 |
| ALLEN  | SALESMAN  | ACCOUNTING | 1600.00 |
| BLAKE  | MANAGER   | OPERATIONS | 2850.00 |
| BLAKE  | MANAGER   | ACCOUNTING | 2850.00 |
| BLAKE  | MANAGER   | RESEARCH   | 2850.00 |
| BLAKE  | MANAGER   | SALES      | 2850.00 |
| CLARK  | MANAGER   | ACCOUNTING | 2450.00 |
| CLARK  | MANAGER   | RESEARCH   | 2450.00 |
| CLARK  | MANAGER   | SALES      | 2450.00 |
| CLARK  | MANAGER   | OPERATIONS | 2450.00 |
| FORD   | ANALYST   | OPERATIONS | 3000.00 |
| FORD   | ANALYST   | SALES      | 3000.00 |
| FORD   | ANALYST   | RESEARCH   | 3000.00 |
| FORD   | ANALYST   | ACCOUNTING | 3000.00 |
| JAMES  | CLERK     | OPERATIONS |  950.00 |
| JAMES  | CLERK     | SALES      |  950.00 |
| JAMES  | CLERK     | RESEARCH   |  950.00 |
| JAMES  | CLERK     | ACCOUNTING |  950.00 |
| JONES  | MANAGER   | SALES      | 2975.00 |
| JONES  | MANAGER   | ACCOUNTING | 2975.00 |
| JONES  | MANAGER   | RESEARCH   | 2975.00 |
| JONES  | MANAGER   | OPERATIONS | 2975.00 |
| KING   | PRESIDENT | OPERATIONS | 5000.00 |
| KING   | PRESIDENT | SALES      | 5000.00 |
| KING   | PRESIDENT | RESEARCH   | 5000.00 |
| KING   | PRESIDENT | ACCOUNTING | 5000.00 |
| MARTIN | SALESMAN  | ACCOUNTING | 1250.00 |
| MARTIN | SALESMAN  | RESEARCH   | 1250.00 |
| MARTIN | SALESMAN  | SALES      | 1250.00 |
| MARTIN | SALESMAN  | OPERATIONS | 1250.00 |
| MILLER | CLERK     | OPERATIONS | 1300.00 |
| MILLER | CLERK     | SALES      | 1300.00 |
| MILLER | CLERK     | RESEARCH   | 1300.00 |
| MILLER | CLERK     | ACCOUNTING | 1300.00 |
| SCOTT  | ANALYST   | OPERATIONS | 3000.00 |
| SCOTT  | ANALYST   | ACCOUNTING | 3000.00 |
| SCOTT  | ANALYST   | RESEARCH   | 3000.00 |
| SCOTT  | ANALYST   | SALES      | 3000.00 |
| SMITH  | CLERK     | OPERATIONS |  800.00 |
| SMITH  | CLERK     | ACCOUNTING |  800.00 |
| SMITH  | CLERK     | RESEARCH   |  800.00 |
| SMITH  | CLERK     | SALES      |  800.00 |
| TURNER | SALESMAN  | ACCOUNTING | 1500.00 |
| TURNER | SALESMAN  | RESEARCH   | 1500.00 |
| TURNER | SALESMAN  | SALES      | 1500.00 |
| TURNER | SALESMAN  | OPERATIONS | 1500.00 |
| WARD   | SALESMAN  | ACCOUNTING | 1250.00 |
| WARD   | SALESMAN  | RESEARCH   | 1250.00 |
| WARD   | SALESMAN  | SALES      | 1250.00 |
| WARD   | SALESMAN  | OPERATIONS | 1250.00 |
+--------+-----------+------------+---------+
56 rows in set (0.00 sec

四、内部联结

等值联结

基于两个表之间的相等测试

内部联结

内部联结定义和等值联结定义差不多。

内部联结的新语法(INNER JOIN …ON…)

mysql> select ename,job ,dname ,sal 
       from emp 
       inner join dept 
       on emp.deptno = dept.deptno;
+--------+-----------+------------+---------+
| ename  | job       | dname      | sal     |
+--------+-----------+------------+---------+
| SMITH  | CLERK     | RESEARCH   |  800.00 |
| ALLEN  | SALESMAN  | SALES      | 1600.00 |
| WARD   | SALESMAN  | SALES      | 1250.00 |
| JONES  | MANAGER   | RESEARCH   | 2975.00 |
| MARTIN | SALESMAN  | SALES      | 1250.00 |
| BLAKE  | MANAGER   | SALES      | 2850.00 |
| CLARK  | MANAGER   | ACCOUNTING | 2450.00 |
| SCOTT  | ANALYST   | RESEARCH   | 3000.00 |
| KING   | PRESIDENT | ACCOUNTING | 5000.00 |
| TURNER | SALESMAN  | SALES      | 1500.00 |
| ADAMS  | CLERK     | RESEARCH   | 1100.00 |
| JAMES  | CLERK     | SALES      |  950.00 |
| FORD   | ANALYST   | RESEARCH   | 3000.00 |
| MILLER | CLERK     | ACCOUNTING | 1300.00 |
+--------+-----------+------------+---------+
14 rows in set (0.00 sec)

分析:

  • FROM子句:

两个表之间的关系时FROM子句的组成部分,用INNNER JOIN指定

  • ON子句:

两个表之间的联结规则由ON子句指定

ANSI SQL规范首选INNER JOIN语法

五、性能考虑

MySQL在运行时关联指定的每个表以处理联结。 这种处理可能是非常耗费资源的,因此应该仔细,不要联结 不必要的表。联结的表越多,性能下降越厉害。

子查询和联结查询

假设现在我们要查询所有在 NEW YORK 和 CHICAGO工作的员工,但是

员工的工作地址信息存储在部门表中,员工具体姓名存在员工表中。

子查询:

mysql> select ename ,deptno 
       from emp 
       where deptno in (select 
                        deptno 
                        from dept 
                        where loc in ('NEW YORK','CHICAGO'));
+--------+--------+
| ename  | deptno |
+--------+--------+
| ALLEN  |     30 |
| WARD   |     30 |
| MARTIN |     30 |
| BLAKE  |     30 |
| CLARK  |     10 |
| KING   |     10 |
| TURNER |     30 |
| JAMES  |     30 |
| MILLER |     10 |
+--------+--------+
9 rows in set (0.00 sec)

联结查询:

mysql> select ename, emp.deptno ,loc 
       from emp inner 
       join dept 
       on emp.deptno = dept.deptno ;
+--------+--------+----------+
| ename  | deptno | loc      |
+--------+--------+----------+
| SMITH  |     20 | DALLAS   |
| ALLEN  |     30 | CHICAGO  |
| WARD   |     30 | CHICAGO  |
| JONES  |     20 | DALLAS   |
| MARTIN |     30 | CHICAGO  |
| BLAKE  |     30 | CHICAGO  |
| CLARK  |     10 | NEW YORK |
| SCOTT  |     20 | DALLAS   |
| KING   |     10 | NEW YORK |
| TURNER |     30 | CHICAGO  |
| ADAMS  |     20 | DALLAS   |
| JAMES  |     30 | CHICAGO  |
| FORD   |     20 | DALLAS   |
| MILLER |     10 | NEW YORK |
+--------+--------+----------+
14 rows in set (0.00 sec)

注意:

select 主句后的列名如果在多个表中出现多义性时候必须使用完全限定名(前面加上所在表明,如emp.deptno),否则会报字段模糊错误。

mysql> select ename, deptno , loc from emp inner join dept on emp.deptno = dept.deptno;
ERROR 1052 (23000): Column 'deptno' in field list is ambiguous

六、使用表别名

别名除了可用于被检索的列名和可计算字段以外,同样可以用于表名的别名。

优点:

  • 缩短SQL语句
  • 允许在一条SQL语句中多次使用相同的表

示例:

mysql> select ename ,em.deptno ,loc 
	   from emp as em , dept as de 
	   where em.deptno =
de.deptno;
+--------+--------+----------+
| ename  | deptno | loc      |
+--------+--------+----------+
| SMITH  |     20 | DALLAS   |
| ALLEN  |     30 | CHICAGO  |
| WARD   |     30 | CHICAGO  |
| JONES  |     20 | DALLAS   |
| MARTIN |     30 | CHICAGO  |
| BLAKE  |     30 | CHICAGO  |
| CLARK  |     10 | NEW YORK |
| SCOTT  |     20 | DALLAS   |
| KING   |     10 | NEW YORK |
| TURNER |     30 | CHICAGO  |
| ADAMS  |     20 | DALLAS   |
| JAMES  |     30 | CHICAGO  |
| FORD   |     20 | DALLAS   |
| MILLER |     10 | NEW YORK |
+--------+--------+----------+
14 rows in set (0.00 sec)



mysql> select ename, emp.deptno ,loc 
	   from emp 
	   inner join dept as de 
	   on emp.deptno = de.deptno ;
+--------+--------+----------+
| ename  | deptno | loc      |
+--------+--------+----------+
| SMITH  |     20 | DALLAS   |
| ALLEN  |     30 | CHICAGO  |
| WARD   |     30 | CHICAGO  |
| JONES  |     20 | DALLAS   |
| MARTIN |     30 | CHICAGO  |
| BLAKE  |     30 | CHICAGO  |
| CLARK  |     10 | NEW YORK |
| SCOTT  |     20 | DALLAS   |
| KING   |     10 | NEW YORK |
| TURNER |     30 | CHICAGO  |
| ADAMS  |     20 | DALLAS   |
| JAMES  |     30 | CHICAGO  |
| FORD   |     20 | DALLAS   |
| MILLER |     10 | NEW YORK |
+--------+--------+----------+
14 rows in set (0.00 sec)

注意:

SELECT 主句后面的检索列使用完全限定名的时候也必须使用别名,否则无法识别检索列

上一篇:线程通信的应用:经典例题:生产者/消费者问题


下一篇:mysql之mysql学习准备的数据库04