SQL中on和where的区别
SQL中on和where的区别
前言,在工作写SQL使用中,在涉及到多个表的关联时,既可以通过on进行数据过滤,又可以使用where进行数据过滤,
确实有点不太了解这两个关键字在left join后的区别,所以就去查了些资料,方便以后回顾。
→省流:看结论拉到最后←
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。
在使用 left join 时,on 和 where 条件的区别如下:
- 1、on 条件是在生成临时表时使用的条件,它不管 on 中的条件是否为真,都会返回左边表中的记录。
- 2、where 条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有 left join 的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
下面有两个表,用户表和用户地址表:表示用户和地址是1对多的关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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’)
1 2 3 4 5 6 7 8 9 | 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 后面,会发现王五这个用户信息没有了,王五只是没有地址,不应该他也被过滤掉
1 2 3 4 5 6 7 8 9 10 11 | 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条件后面,如下:
1 2 3 4 5 6 7 8 9 10 | 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后面!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话