SQL中on和where的区别

SQL中on和where的区别
  前言,在工作写SQL使用中,在涉及到多个表的关联时,既可以通过on进行数据过滤,又可以使用where进行数据过滤,

确实有点不太了解这两个关键字在left join后的区别,所以就去查了些资料,方便以后回顾。

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

在使用 left join 时,on 和 where 条件的区别如下:

1、on 条件是在生成临时表时使用的条件,它不管 on 中的条件是否为真,都会返回左边表中的记录。
2、where 条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有 left join 的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
下面有两个表,用户表和用户地址表:表示用户和地址是1对多的关系

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `is_delete` int DEFAULT '0' COMMENT '0表示未删除,1表示已删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
 
INSERT INTO `demo`.`t_user` (`id`, `name`, `age`, `is_delete`) VALUES (1, '张三', 23, 0);
INSERT INTO `demo`.`t_user` (`id`, `name`, `age`, `is_delete`) VALUES (2, '李四', 24, 1);
INSERT INTO `demo`.`t_user` (`id`, `name`, `age`, `is_delete`) VALUES (3, '王五', 25, 0);
 
 
CREATE TABLE `t_address` (
  `id` int NOT NULL AUTO_INCREMENT,
  `user_id` int DEFAULT NULL COMMENT '用户id',
  `address` varchar(255) DEFAULT NULL COMMENT '地址',
  `is_delete` int DEFAULT NULL COMMENT '0表示未删除,1表示已删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户地址表';
 
INSERT INTO `demo`.`t_address` (`id`, `user_id`, `address`, `is_delete`) VALUES (1, 1, '北京朝阳', 0);
INSERT INTO `demo`.`t_address` (`id`, `user_id`, `address`, `is_delete`) VALUES (2, 1, '北京丰台', 0);
INSERT INTO `demo`.`t_address` (`id`, `user_id`, `address`, `is_delete`) VALUES (3, 2, '北京西城', 1);
INSERT INTO `demo`.`t_address` (`id`, `user_id`, `address`, `is_delete`) VALUES (4, 5, '北京海淀', 1);

在这里插入图片描述
如果要查询已存在用户的地址信息,应该写在on后面还是where条件后面呢?请看下面示例:

条件都写在on后面(×)

如果将条件都写在on 后面,会发现用户表中is_delete为1的数据并没有被过滤(即使在on后面写了过滤条件‘u.is_delete = 0’)

SELECT
    u.`name`,
    u.age,
    u.is_delete,
    a.address
FROM
    t_user u
    LEFT JOIN t_address a ON u.id = a.user_id and u.is_delete = 0
    AND a.is_delete = 0;

在这里插入图片描述
条件都写在where后面(×)

如果将条件都写在on 后面,会发现王五这个用户信息没有了,王五只是没有地址,不应该他也被过滤掉

SELECT
    u.`name`,
    u.age,
    u.is_delete,
    a.address
FROM
    t_user u
    LEFT JOIN t_address a ON u.id = a.user_id
WHERE
    u.is_delete = 0
    AND a.is_delete = 0;

在这里插入图片描述
正确写法

在被left join的‘地址表’中的条件应该写在on后面

主表的条件应该写在where条件后面,如下:

SELECT
    u.`name`,
    u.age,
    u.is_delete,
    a.address
FROM
    t_user u
    LEFT JOIN t_address a ON u.id = a.user_id and a.is_delete = 0
WHERE
    u.is_delete = 0;

在这里插入图片描述
总结:

left join 进行表关联时,关联表(主表)的过滤条件放在where后面,被关联表(子表)的过滤条件放在on后面!

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

princeAladdin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值