SQL中on和where的区别

发布于:2024-07-12 ⋅ 阅读:(133) ⋅ 点赞:(0)

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


网站公告

今日签到

点亮在社区的每一天
去签到