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后面!

posted @   Java小白的搬砖路  阅读(675)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话

喜欢请打赏

扫描二维码打赏

支付宝打赏

点击右上角即可分享
微信分享提示