在本科时期,其实这个问题困扰了我很久,最早都是用如下语句,也就是笛卡尔积的形式。
select **
from A,B
where A.name=B.name
再熟悉了各种联表以后其实这就是cross join,是最慢的一种联表方式,会返回A表字段的数据*B表字段的数据(如果A表有10条数据,B表有20条数据,那么最后返回结果就是200条)。
其实可以根据真实的需求用更好的联表操作,如left join 或inner join。
红烧排骨饭博客中给出的例子很容易理解
商品表
CREATE TABLE product (
id int,
name varchar(100) COMMENT '名称',
img_id int COMMENT '关联的图片id'
);
图片表
CREATE TABLE image (
id int,
url varchar(500) COMMENT '图片的url'
);
图片表有4条数据
INSERT INTO image (id, url) VALUES
(1, 'f7c27424b538281fee5f00db5f83c2de.jpg'),
(2, '522748524ad010358705b6852b81be4c.png'),
(3, '97adf9fdd4c3e8423f37a208beb47a7a.gif'),
(4, '7b1847d909f17365bec38b04b9da6e57.webp');
商品表
INSERT INTO product (id, name, img_id) VALUES
(1, '杯子', 1),
(2, '电脑', null),
(3, '大米饭', 3),
(4, 'PS4', null);
有一个需求 查询所有商品的所有信息
SELECT
product.id,
product.name,
image.url
FROM
product inner join image on product.img_id = image.id
id | name | url |
---|---|---|
1 | 杯子 | ‘f7c27424b538281fee5f00db5f83c2de.jpg’ |
3 | 大米饭 | ‘97adf9fdd4c3e8423f37a208beb47a7a.gif’ |
这样的结果看起不对,没有列出所有的商品。因为商品的记录有4条,这里只列出了2条。另外两个没有图片的商品哪里去了?
SELECT
product.id,
product.name,
image.url
FROM
product
LEFT JOIN image ON product.img_id = image.id
返回结果
id | name | url |
---|---|---|
1 | 杯子 | ‘f7c27424b538281fee5f00db5f83c2de.jpg’ |
3 | 大米饭 | ‘97adf9fdd4c3e8423f37a208beb47a7a.gif’ |
2 | 电脑 | |
4 | PS4 |
注意:
- 如果单纯看逻辑运算数量,inner join会比left join更优,因为inner join会返回两表的交集,而left join会返回左表的全部记录。并且inner join会默认使用较小的表作为主表进行循环。
- 但是有时候inner join也会比left join 慢,具体原因需要具体分析,这里举个例子:大表的连接字段没有建索引,小表建索引了,然后left join中左表是大表,在循环查找会使用小表的索引,而inner join会自动使用小表作为主表,然后循环查找大表(无法使用索引),所以就会很慢。