多表联查--01---LEFT JOIN 实现多表联查

表的关系

  • 一对一,一张表 有时候会为了性能而拆开(商品信息和商品备注信息–详情-很大)
  • 一对多,必须两张表
  • 多对一,反过来就是一对多,必须两张表
  • 多对多,必须三张表,中间表,来维护它们之间的关系
    在这里插入图片描述

笛卡尔积查询:

  • 所谓笛卡尔积查询就是指,查询两张表,其中一张表有m条记录,另一张表有n条记录,查询的结果是m*n条。
笛卡尔积。
现在,我们有两个集合A和B。 A = {0,1} B = {2,3,4}

集合 A×B 和 B×A的结果集就可以分别表示为以下这种形式:

A×B = {(0,2),(1,2),(0,3),(1,3),(0,4),(1,4)};

B×A = {(2,0),(2,1),(3,0),(3,1),(4,0),(4,1)};

以上A×B和B×A的结果就可以叫做两个集合相乘的‘笛卡尔积’。

查询复杂度

例如: A表 n条记录,B表m条记录

  1. 表连接查询 select * from A left B on , 复杂度 n+m
  2. 相关子查询 select * from A IN (select * from B) , 复杂度 n*m

所以 mysql查询优化器可能对涉及子查询的查询语句进行重写, 转变为多表查询的操作,已降低查询的复杂度
在这里插入图片描述
在这里插入图片描述

案例:

tab1

在这里插入图片描述

tab2

在这里插入图片描述

SELECT * FROM tab1 ,tab2 ;

  • 笛卡尔积=3*3=9

在这里插入图片描述

where 和 left join区别

数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。

区别:

1. on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录

2. where条件是在临时表生成好后,再对临时表进行过滤的条件。

这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

案例:

tab1

在这里插入图片描述

tab2

在这里插入图片描述

WHERE:

SELECT * FROM tab1 ,tab2 WHERE tab1.size = tab2.size ;

在这里插入图片描述

LEFT JOIN ON:

SELECT * FROM tab1 LEFT JOIN tab2 ON tab1.size = tab2.size;

在这里插入图片描述

SELECT * FROM tab1 LEFT JOIN tab2 ON tab1.size != tab2.size

在这里插入图片描述

解析:

1.数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表

相当于 SELECT * FROM tab1 ,tab2 ; ==> 中间的临时表

在这里插入图片描述

2.LEFT JOIN on条件是在生成临时表时使用的条件,

SELECT * FROM tab1 LEFT JOIN tab2 ON tab1.size != tab2.size;
其中tab1.size != tab2.size 是条件 在这里插入图片描述

3.不管LEFT JOIN on中的条件是否为真,都会返回左边表中的记录

SELECT * FROM tab1 LEFT JOIN tab2 ON tab1.size = tab2.size;

在这里插入图片描述

4. 我们再看where 多表联查:

SELECT * FROM tab1 , tab2 WHERE tab1.size = tab2.size;

在这里插入图片描述

where条件是在临时表生成好后,再对临时表进行过滤帅选

同理:

SELECT * FROM tab1 , tab2 WHERE tab1.size != tab2.size;

在这里插入图片描述

LEFT JOIN , RIGHT JOIN ,INNER JOIN对比

概念:

  • left join(左联接) :把左边的全部查出来,右边有的则匹配,没有则为null
  • right join(右联接) :返回包括右表中的所有记录,和左表中联结字段相等的记录
  • inner join(等值连接): 只返回两个表中联结字段相等的行

案例:

tab1

在这里插入图片描述

tab2

在这里插入图片描述

SELECT * FROM tab1 ,tab2;

在这里插入图片描述

条件为tab1 .size = tab2.size;

SELECT * FROM tab1 , tab2 WHERE tab1.size = tab2.size;
在这里插入图片描述

SELECT * FROM tab1 LEFT JOIN tab2 ON tab1.size = tab2.size;
在这里插入图片描述

SELECT * FROM tab1 RIGHT JOIN tab2 ON tab1.size = tab2.size;
在这里插入图片描述

SELECT * FROM tab1 INNER JOIN tab2 ON tab1.size = tab2.size;
在这里插入图片描述

条件为tab1 .size != tab2.size

SELECT * FROM tab1 , tab2 WHERE tab1.size != tab2.size;
在这里插入图片描述

SELECT * FROM tab1 LEFT JOIN tab2 ON tab1.size != tab2.size;
在这里插入图片描述

SELECT * FROM tab1 RIGHT JOIN tab2 ON tab1.size != tab2.size
在这里插入图片描述

SELECT * FROM tab1INNER JOIN tab2 ON tab1.size != tab2.size
在这里插入图片描述

另: 只查询左表字段的的记录

SELECT tab1.id, tab1.salary, tab1.size
FROM tab1 LEFT JOIN tab2 ON tab1.size != tab2.size;

在这里插入图片描述

看上去像有重复记录,实际是没查全

在这里插入图片描述

中间临时表在这里插入图片描述

加上 DISTINCT
SELECT DISTINCT tab1.id, tab1.salary, tab1.size
FROM tab1 LEFT JOIN tab2 ON tab1.size != tab2.size

在这里插入图片描述

解析:

因为on的条件tab1.size != tab2.size ,左表一条匹配到右边记录多条,所以单看左表会显示重复记录

如果要唯一 可以使用where 在on之后进行筛选,或者on后的条件 是一 一匹配.

题目:

需求:找出表tab1中 size和tab2中size不相等的记录

tab1

在这里插入图片描述

tab2

在这里插入图片描述

不能直接用left join on 去找

SELECT tab1.id,tab1.salary,tab1.size
FROM tab1 LEFT JOIN tab2 ON tab1.size != tab2.size;

在这里插入图片描述
在这里插入图片描述

因为: tab1.size != tab2.size ,左表一条匹配到右边记录多条,所以单看左表会显示重复记录

正确写法 1:

先找到相等的记录 ,在筛选

SELECT tab1.id,tab1.salary,tab1.size FROM tab1 WHERE tab1.id NOT IN (
SELECT tab1.id FROM tab1 INNER JOIN tab2 ON tab1.size = tab2.size );

在这里插入图片描述

或者

SELECT tab1.id,tab1.salary,tab1.size FROM tab1 WHERE tab1.id NOT IN (
SELECT tab1.id FROM tab1 , tab2 WHERE tab1.size = tab2.size );

注意:

上诉sql不能用left JOIN on 或者 right JOIN on

left 会默认返回所有 tab1.id

SELECT tab1.id FROM tab1 LEFT JOIN tab2 ON tab1.size = tab2.size
在这里插入图片描述

right 返回结果集 会有null 记录

- SELECT tab1.id FROM tab1 RIGHT JOIN tab2 ON tab1.size = tab2.size

在这里插入图片描述

INNER JOIN

SELECT * FROM tab1 INNER JOIN tab2 ON tab1.size = tab2.size

在这里插入图片描述
在这里插入图片描述

总结:

  1. 对于left join,不管on后面跟什么条件,左表的数据全部查出来,因此要想过滤需把条件放到where后面

  2. 对于inner join,满足on后面的条件表的数据才能查出,可以起到过滤作用。也可以把条件放到where后面。

正确写法 2:

not in 效率不高 可以考虑 not exists

SELECT id ,size,salary FROM tab1 AS a WHERE NOT EXISTS(
SELECT tab1.id FROM tab1 INNER JOIN tab2 =ON tab1.size =tab2.size
WHERE tab1.id= a.id )

在这里插入图片描述

正确写法 3:

SELECT tab1.id,tab1.salary,tab1.size FROM tab1 WHERE size NOT IN (
SELECT size FROM tab2 )

在这里插入图片描述

  • 29
    点赞
  • 169
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在 Mybatis-Plus 中进行多表联查时,可以使用 `@TableField` 注解指定要查询的字段,并在实体类中定义对应的属性。 假设我们有两张表:`user` 表和 `order` 表,它们的关系是一对多,一个用户可以拥有多个订单。现在我们需要查询用户的信息和他的订单总数,然后将订单总数更新到用户表中的一个字段中。 首先,定义一个实体类 `User`,并在其中添加一个属性 `orderCount`,用来存储订单总数: ``` @Data public class User { private Long id; private String name; private Integer age; @TableField(exist = false) private Integer orderCount; // 订单总数 } ``` 其中,`@TableField(exist = false)` 表示该属性不是数据库表中的字段。 然后,使用 Mybatis-Plus 提供的 `Wrapper` 类进行多表联查,并计算订单总数: ``` QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.select("user.*, COUNT(order.id) as order_count") .eq("user.id", userId) .leftJoin("order", "user.id=order.user_id") .groupBy("user.id"); User user = userMapper.selectOne(wrapper); if (user != null) { user.setOrderCount(orderCount); userMapper.updateById(user); } ``` 在 `wrapper.select()` 方法中,我们使用了 SQL 的聚合函数 `COUNT()` 来计算订单总数,并使用 `as` 关键字给计算结果取了一个别名 `order_count`。然后,在 `wrapper.leftJoin()` 方法中,指定了要联查的表和联查条件。最后,在 `wrapper.groupBy()` 方法中,指定了分组条件。 查询出用户信息后,将订单总数设置到 `User` 对象中,并使用 `userMapper.updateById()` 方法将修改后的数据更新到数据库中。 以上就是使用 Mybatis-Plus 进行多表联查并修改字段的方法。注意,这里的 `orderCount` 属性不是数据库表中的字段,因此需要使用 `@TableField(exist = false)` 注解标识。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值