>[success] # 表的联结
>SQL 最强大的功能之一就是能在数据检索查询的执行中联结表。
数据是存储在关系表中的,关系表的设计原则是保证把信息分解为多个表, 一类数据一个表,各表通过某些常用的值互相关联。
两个表之间的关联关系通过外键来关联。
外键是某个表中的一列,它包含另外一个表的主键值,定义了两个表之间的 关系。
<br>
* * * * *
>[danger] ##### 创建联结
>解释说明,两个表相互联结时,要用where指定他们的关系列,利用select * from 后可以跟多个表,通过查询多个表找到关系
**有一个user表用来存放用户名字**
![](https://box.kancloud.cn/595ad33bb8c981cd70305a282002fe38_173x81.png)
**有一个uu表 用来存放qq号**
![](https://box.kancloud.cn/a12bfcd2b9da2699b67ec53a85595ecc_168x77.png)
**两表唯一关联时nid字段,我们用联合查询,将表联结**
`SELECT user.nid,user.`userrname`,uu.`qq` FROM USER,uu WHERE user.`nid`=uu.`nid`;`
**结果如图**:
![](https://box.kancloud.cn/441fc7c508528d79d29d1c6cdeceb6fb_276x62.png)
>[danger] 联结常犯错误-笛卡尔积
>笛卡尔积是由没有联结条件的表关系返回的结果,检索出的行的数目将是第 一个表中的行数乘以第二个表中的行数,通俗的说关联的表,无论两个还多个,他们之间无对应的where条件关系导致,差生数据查询混乱
`SELECT user.nid,user.`userrname`,uu.`qq` FROM USER,uu ;`
因为没有限制where 条件导致联结是,出现重复错误数据,实际两条数据通过,笛卡尔积导致四条
![](https://box.kancloud.cn/0e59f5cf0b063bcb5c1745838665dc1f_273x93.png)
* * * * *
<br>
>[danger] ##### 内部联结-inner join.........on
>此语句中的 select 与前面的 select 语句相同,但 from 子句不同,这里 两个表之间的关系是 from 子句的组成部分,以 INNER JOIN 指定。在使用这 种语法时,联结条件用特定的 ON 子句而不是 where 子句。传递给 ON 的实 际条件与传递给 where 的相同
**语法:**
` select 列 from 表一 inner join 表二 on 联结相关连字段 `
**案列:**
`SELECT user.nid,user.`userrname`,uu.`qq` FROM USER INNER JOIN uu ON user.nid=uu.`nid` ;`
![](https://box.kancloud.cn/950b476a4ff34c7fd47f1e4441112e6b_247x57.png)
**注意:**
MySQL 在运行时关联指定的每个表以处理联结,这种处理可能非常消 耗资源,因此不要联结不必要的表。联结的表越多,性能下降越厉害。
* * * * *
<br>
>[danger] ##### 自连接
**传统的子查询:**
有种情况,一个表中有一个商品vend_id 的列,我们想查找DINTR这个商品在哪个标号,查出的编号下,又有那些物品,整合的sql
`SELECT * FROM products WHERE vend_id = (SELECT vend_id FROM products WHERE prod_id='DTNTR')`
**使用自联结 :**
`SELECT p1.`prod_id`,p1.`prod_name` FROM products AS p1, products AS p2 WHERE p1.vend_id = p2.`vend_id` AND p2.`prod_id`='DTNTR';`
**注:**
个人理解,因为自连接两个表时一样的 ,我们在where查询的时候,条件是p2,所以展示应给用p1列来做,因为p2查出来的数据是针对的
* * * * *
<br>
>[danger] ##### 左连接:
>以左边表为基准,按照过滤条件查找右边表的记录,如果匹配到, 那么就组合成一行,并显示结果,如果没有匹配到,那么只显示左边表的字 段,右边表中不存在的字段用空值来表示。
>A表所有显示,如果B中无对应关系,则值为null
select A.num, A.name, B.name
from A left join B
on A.nid = B.nid
* * * * *
<br>
>[danger] ##### 右连接:
>作用和左联结刚好相反,以右边表为基准,去匹配左边的表,如果 左边表字段为空,那么就用空值来表示。
>B表所有显示,如果B中无对应关系,则值为null
select A.num, A.name, B.name
from A right join B
on A.nid = B.nid