left join陷阱

0 阅读2分钟

说明:本文介绍数据库表关联查询,left join 使用的坑,以 MySQL 为例,假设有以下两张表,学生表、班级表

(学生表)

在这里插入图片描述

在这里插入图片描述

(班级表)

在这里插入图片描述

在这里插入图片描述

场景一:逻辑删除

如下,分页查询学生列表信息,并关联查询学生的班级信息,为了过滤掉逻辑删除的记录,给每张表都加上了 deleted = false 条件

-- 分页查询学生列表(方式一)
select t1.id, t1.name, t2.class_name, t2.teacher_name
from tb_student t1
         left join tb_class t2 on t1.class_id = t2.id
where t1.deleted = false
  and t2.deleted = false
limit 0, 100

执行,发现没有关联到班级的学生记录没有查出来

在这里插入图片描述

原因在于 t2.deleted = false 条件,没有关联到班级的学生记录,没有这个字段,自然会被过滤掉。但又不能直接去掉该条件,不然就有脏数据。

可修改 SQL 如下,将逻辑删除条件加到关联上

-- 分页查询学生列表(方式二)
select t1.id, t1.name, t2.class_name, t2.teacher_name
from tb_student t1
         left join tb_class t2 on t1.class_id = t2.id and t2.deleted = false
where t1.deleted = false
limit 0, 100

这就能查出来了

在这里插入图片描述

场景二:主表关联子表

新增一张表,专门用来存学生的联系人信息,如下:

在这里插入图片描述

添加几条数据

在这里插入图片描述

查询学生信息

-- 查询学生信息
select t1.id, t1.student_no, t1.name, t2.contact_person_name, t2.contact_person_phone
from tb_student t1
         left join tb_student_contact_info t2 on t1.student_no = t2.student_no and t2.deleted = false
where t1.deleted = false
limit 0, 100

可以看到,因为学生表与联系人表是 一对多 的关系,所以做关联查询的时候,学生记录有重复

在这里插入图片描述

要避免这种情况,有两个办法,要么在代码里封装,学生对象里封装一个联系人集合,这样能保证学生记录是单条;要么不返回联系人字段,用学生信息 group by,如下:

select t1.id, t1.student_no, t1.name
from tb_student t1
         left join tb_student_contact_info t2 on t1.student_no = t2.student_no and t2.deleted = false
where t1.deleted = false
group by t1.id, t1.student_no, t1.name
limit 0, 100;

这样不会出现重复的学生记录。既保留了联系人表 t2 的查询条件(如果要对 t2 表加筛选条件),又保证了查询结果是以学生维度展示的。

在这里插入图片描述

总结

本文介绍了数据库表关联查询值得注意的两个点

首次发布

hezhongying.blog.csdn.net/article/det…