表:A、B
A 字段:id,name
B 字段:id,a_id
关键名词:主表、关联表、关联条件、筛选条件
例子:
# 主表:A、关联表:B、关联条件:A.od=B.a_id、筛选条件:B.id=1
A left join B on A.id=B.a_id and B.id=1
- 结论:
- 表 A 和表 B 的连接依靠关联条件
- 主表的筛选条件,应该放置在 where 条件后
- on 后面的筛选条件是针对于关联表
- 关联表的筛选条件,如果放置在 on 后面,那么 A 和 B 的连接顺序为:B 表先按条件查询,再与 A 表连接,即先筛选再连接;
- 如果放置在 where 后面,那么 A 和 B 的连接顺序为:A 与 B 连接后,再从连接表中筛选,即先连接再筛选
- where 后面的条件是对连接后的数据进行筛选
- 如果存在多个left join on,请注意on后面的条件与哪个表关联。这一条统计的SQL很重要!例如表A,B,C,A left join B on A.x = B.x left join C on A.x = C.x,B和C的都要和A建立关联,B和C之间是没有任何数据上的关系。但是 如果把A.x = C.x改成B.x = C.x,那么B和C的表数据先建立关联并过滤数据,再与A表数据进行关联,这样可能会出现数据丢失!详细案例,点这里查看
一、验证结论第2条:主表的筛选条件应该放置在 where 条件后
- 主表的筛选条件应该放置在 where 条件后,如果放在 on 后面,对主表的查询没有意义,而且查询的结果也是不正确的。
-- 验证结论3:
-- #错误的示范:主表的筛选条件在 on 后,是错误的,on对关联表起作用。
-- 正确的做法:对主表的筛选条件放在where后面
SELECT * from
edu_student stu
left JOIN edu_score score ON stu.id = score.stu_id and stu.stu_name='盲僧';
-- # 区别于
-- # 验证结论5:主表的筛选条件在 where 后
SELECT * from
edu_student stu
left JOIN edu_score score ON stu.id = score.stu_id where stu.stu_name='盲僧';
从Result1结果来看:将主表的筛选条件放在on后面,查询的结果是错误的。
从Result2结果来看:查询正确,那么就要记住:以后主表的筛选条件放在where后面。
二、验证结论第2条:关联表先筛选再连接主表
-- # 关联表的筛选条件放在 on 后面
-- # 关联表先筛选再连接主表
SELECT * from
edu_student stu
left JOIN edu_score score ON stu.id = score.stu_id and score.scores > 90;
-- # 等价于
SELECT * FROM edu_student stu
LEFT JOIN ( SELECT * FROM edu_score score WHERE score.scores > 90 ) a
ON stu.id = a.stu_id;
从结果1、结果2来看,查询正确。
三、验证结论:关联表的筛选条件放在 where 后,主表、关联表先连接,再筛选
-- # 关联表的筛选条件放在 where 后
-- # 主表、关联表先连接,再筛选
SELECT * from
edu_student stu
left JOIN edu_score score ON stu.id = score.stu_id
where score.scores > 90;
-- 左连接数据
SELECT * from
edu_student stu
left JOIN edu_score score ON stu.id = score.stu_id
sql脚本:
学生表edu_student
CREATE TABLE `edu_student` (
`id` varchar(16) NOT NULL COMMENT '学号',
`stu_name` varchar(20) NOT NULL COMMENT '学生姓名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生表';
-- ----------------------------
-- Records of edu_student
-- ----------------------------
INSERT INTO `edu_student` VALUES ('1001', '盲僧');
INSERT INTO `edu_student` VALUES ('1002', '赵信');
INSERT INTO `edu_student` VALUES ('1003', '皇子');
INSERT INTO `edu_student` VALUES ('1004', '寒冰');
INSERT INTO `edu_student` VALUES ('1005', '蛮王');
INSERT INTO `edu_student` VALUES ('1006', '狐狸');
成绩表edu_score
CREATE TABLE `edu_score` (
`stu_id` varchar(16) NOT NULL COMMENT '学号',
`course_no` varchar(20) NOT NULL COMMENT '课程编号',
`scores` float DEFAULT NULL COMMENT '得分',
PRIMARY KEY (`stu_id`,`course_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='成绩表';
-- ----------------------------
-- Records of edu_score
-- ----------------------------
INSERT INTO `edu_score` VALUES ('1001', 'C001', '67');
INSERT INTO `edu_score` VALUES ('1001', 'C002', '87');
INSERT INTO `edu_score` VALUES ('1001', 'C003', '83');
INSERT INTO `edu_score` VALUES ('1002', 'C001', '68');
INSERT INTO `edu_score` VALUES ('1002', 'C002', '88');
INSERT INTO `edu_score` VALUES ('1002', 'C003', '84');
INSERT INTO `edu_score` VALUES ('1003', 'C001', '69');
INSERT INTO `edu_score` VALUES ('1003', 'C002', '89');
INSERT INTO `edu_score` VALUES ('1003', 'C003', '85');
INSERT INTO `edu_score` VALUES ('1004', 'C001', '70');
INSERT INTO `edu_score` VALUES ('1004', 'C002', '90');
INSERT INTO `edu_score` VALUES ('1005', 'C001', '71');
INSERT INTO `edu_score` VALUES ('1005', 'C002', '91');
INSERT INTO `edu_score` VALUES ('1006', 'C001', '72');
INSERT INTO `edu_score` VALUES ('1006', 'C002', '92');