【联表查询中的隐蔽 bug】

join、left join

  • JOIN(INNER JOIN)是选择两个表中都有的记录,结果集会排除掉任何不匹配的记录。
  • LEFT JOIN是选择左表的所有记录,右表的记录如果存在则包括在内,不存在则用NULL填充。

举例

前提介绍

  • 下面的sq大致看上去好像没问题。
  • 有三张表 (users用户表、orders订单表、order_user用户和订单的关联表表示参加这个订单的用户) 。
  • 很明显,这个sql对应的需求应该是查询所有订单,并且联表查询出参加这个订单的用户,也就是及时这个订单没有用户参与也要将这条订单查出。
  • 但是,现在情况是当order_user没有记录与orders对应时,这条订单不能被查出。
sql 复制代码
select orders.id             AS order_id,
      // ... 省略一些字段
       orders.description    AS order_description,
       
       users.id              AS user_id,
        // ... 省略一些字段
       users.description     AS user_description
from orders
         join order_user on orders.id = order_user.order_id
         left join users on users.id = order_user.user_id
where orders.is_delete = 0
and order_user.is_delete = 0
and users.is_delete = 0;

问题分析

上面的sql问题出在where后面的条件上,虽然left join不会管右边有没有用户相匹配,但是,where后面的isdelete=0会过滤掉右边为空的记录。

解决办法

将isdelete判断变成联表查询的并列条件。

sql 复制代码
select orders.id             AS order_id,
      // ... 省略一些字段
       orders.description    AS order_description,
       
       users.id              AS user_id,
        // ... 省略一些字段
       users.description     AS user_description
from orders
         left join order_user on orders.id = order_user.order_id and order_user.is_delete = 0
         left join users on users.id = order_user.user_id and users.is_delete = 0
where orders.is_delete = 0;
相关推荐
jiayou643 小时前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
于眠牧北4 小时前
MySQL的锁类型,表锁,行锁,MVCC中所使用的临键锁
mysql
李广坤1 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
Turnip12022 天前
深度解析:为什么简单的数据库"写操作"会在 MySQL 中卡住?
后端·mysql
爱可生开源社区2 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1772 天前
《从零搭建NestJS项目》
数据库·typescript
加号33 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏3 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐3 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再3 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip