>[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