【Mysql必知必会】第15到16章

1.目录

联结,大致上类似于指针,就是将数据用地址的方式【压缩】起来,减少数据的冗余,提高可扩展性。联结我觉得就类似指针的解引用,将表中【压缩】的信息展开回原本的形态。
在这里插入图片描述

2.联结概念

冗余数据的弊端

  • 浪费存储空间。 比如同一供应商的每个产品的供应商信息都是相同的,每个产品中都重复存储一遍相关信息便造成了空间的浪费;
  • 难以改动。 如果供应商信息分布在每个产品中,并且被多次重复,可以想象,改动起来是相当困难的;
  • 重复输入容易产生错误。 假设输入供应商信息时需要重复多次输入相同信息,可以想象,将很容易产生错误,从而导致数据的不一致;

为什么需要联结

可以类比到指针,为什么需要解引用?指针是对数据进行了【压缩】的,这样在用不到的时候就可以减少存储空间,如果要进行传输的话也能少传输很多东西,但是总有需要用到详细信息的时候,这时候肯定就需要【解压缩】了。在指针中这是解引用,在这里便是联结。

主键、外键、可伸缩性、维护应用完整性

  • 主键:一张表中每行数据的标识属性,最典型的就是ID,每行中的主键必须互不相等。当然也可以用多行一同作为主键;
  • 外键:A表用于关联到B表的属性,基本A表中存储的就是B表的主键,大致上就类似B的指针;
  • 可伸缩性:粗略理解就是,外键、主键关联起来的这种形式,在进行信息修改时,例如修改供应商的信息,在独立的供应商表上修改就可以了;
  • 维护应用的完整性,主要是讨论应用合法性的,就是例如供应商外键的值在供应商表中到底存在不存在这类,这章并没有作详细讨论;

3.联结创建

WHERE方法

就我所理解,标准联结(内/外)、自然联结(内/外)都可以用WHERE来进行实现,但是有些联结是比较难用WHERE来做的,用WHERE来实现最典型的内联结:

SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id;

JOIN方法

专门用于联结的关键字,是标准中推荐使用的,而且如果使用NATURAL JOIN的话,写起来相当方便。用JOIN实现WHERE中的例子:

SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;

4.联结类型

具有非常多不同的联结分式,大致上,按照是否需要写联结条件和进行列去重,可分为标准联结和自然联结;按照联结方式可以分为内联结和外联结;

笛卡尔乘积联结

当使用标准内联结(INNER JOIN / JOIN)而省略联结条件的时候,得出的结果就是笛卡尔乘积联结。例如A表有6行,B表有14行,这时候就会得出84行,6*14=84。使用标准外联结(LEFT OUTER JOIN / LEFT JOIN,RIGHT同理),而不写联结条件的话会报错;
例子:

SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products;

标准联结、自然联结

就目前我的理解,自然联结和标准联结的主要区别就是,自然联结是一种提高效率的简化写法。自然联结会自动判断联结条件(就是外键、主键关系,如果没有的话,则进行笛卡尔乘积联结),并且会进行自动的列去重。例子如下:

  • 使用标准联结
SELECT vendors.*, products.prod_id, products.prod_name, 
	products.prod_price, products.prod_desc
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
  • 使用自然联结
SELECT *
FROM vendors NATURAL JOIN products;

不但内联结可以有自然联结实现,外联结也存在相应实现,关键字为:

NATURAL LEFT JOIN
NATURAL RIGHT JOIN

另外,在使用NATURAL RIGHT JOIN等外部联结,是用来处理这类情况的:
A.某个生产商根本没有生产过产品,但需要列出所有生厂商及产品信息,没有产品的话显示NULL;
B.某个客户根本没有下过订单,但需要列出所有客户及订单信息,没有订单的话显示NULL;

所以,会存在A表中外键为NULL,或B表中某个主键在A表没有相应的外键值的情况。
在这种情况下,自然外部联结会重新编排两个表联结后的输出顺序,例如

SELECT * 
FROM products NATURAL RIGHT JOIN vendors 
ORDER BY vend_id;

会先输出vendors的所有列,再在此基础上,如果有对应产品的话就联结相应的产品信息,
然而如果使用标准联结的话,属性输出顺序等是需要自行规定的。

内部联结、外部联结

这里讨论的是通过主键、外键关系联结起来的内部联结和外部联结,不过没有相应关系的话,并且不写联结条件的话,外部联结会直接报错就是了。

  • 内部联结,内部联结是比较常见的联结。例子还是产品和生产商吧,如果采用内部联结的话,则会只有列出【所有生产过产品的生产商,及其生产的产品的联结信息】;
  • 外部联结,外部联结也有不少的应用场景。例子同上,如果采用外部联结,以如下例子来进行说明,
    会列出【被偏向的vendors表中所有的数据,如果vend_id在products有值的话,则在前者的基础上联结相关信息】,例子最终输出【生产过产品的厂商及其所有产品信息,以及没有生产过产品的厂商信息及空的产品信息】;
SELECT * 
FROM products NATURAL RIGHT JOIN vendors 

自联结

一种SQL技巧,例子为书中的【在products表中找出prod_id为DTNTR的行,获取其vend_id;在相同的表中,找出所有具有相同vend_id的行,输出prod_id, prod_name】。

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';

5.其他

别名

  • 列别名,常见于使用函数后进行命名;
  • 表别名,在自联结技巧中是必要的,一般情况下也可用来缩短SQL语句(能少打点字更重要);

使用带聚集函数的联结

联结可以看作一个临时表,当然也是可以使用正常表的GROUP BY、聚集函数、其他函数等的,例子为:

SELECT customers.cust_name,
	customers.cust_id,
	COUNT(orders.order_num) AS num_ord
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id; 

多表联结

  • 虽然不知道效率如何,但是只是实现功能的话不必像书中那么麻烦,在多表联结中也可以直接使用NATURAL JOIN的,【FROM a NATURAL JOIN b NATURAL JOIN c】这样;
  • 多表联结中,可以存在多种联结方式,例如【FROM a NATURAL JOIN b NATURAL LEFT JOIN c】这样;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值