案例1:
场景:表test1有两个字段,分别为int类型的eid字段,varchar类型的ename字段,ename字段值有很多重复的,现需要删除这些重复值并保留eid为最大值的记录。如下表:
CREATE TABLE `test1` (
`eid` int(11) NOT NULL AUTO_INCREMENT,
`ename` varchar(20) DEFAULT NULL,
PRIMARY KEY (`eid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO test1 VALUES(1, 'aaa'),(2, 'aaa'),(3, 'bb'),(4, 'bb'),(5, 'cc');
删除前:
解析:
# 报错。 不允许在一条语句中增删改某个表的记录时,同时还对该表进行子查询
-- DELETE FROM test1 WHERE eid < (SELECT MAX(eid) FROM test1 GROUP BY ename);
# 方式一
DELETE a FROM test1 a LEFT JOIN test1 b ON a.ename = b.ename WHERE a.eid<b.eid;
# 方式二
# SELECT * FROM test1 a LEFT JOIN (SELECT MAX(eid) AS eid FROM test1 GROUP BY ename ) b ON a.eid = b.eid WHERE b.eid IS NULL;
DELETE a FROM test1 a LEFT JOIN (SELECT MAX(eid) AS eid FROM test1 GROUP BY ename ) b ON a.eid = b.eid WHERE b.eid IS NULL;
删除后:
案例2:
Mysql中通过关联字段将一张表的字段更新到另外一张表中
场景: book_borrow表中存储有student表的id和冗余有student表的name字段值,关联条件为book_borrow.student_id = student.id 由于student表有些学生的名字更新了,但是book_borrow表的student_name字段值没更新到
要求: 写一条sql更新book_borrow表的student_name字段值为student表的name字段值
表结构
student表
CREATE TABLE student (
id BIGINT ( 20 ) NOT NULL AUTO_INCREMENT COMMENT '自增id',
name VARCHAR ( 30 ) DEFAULT NULL COMMENT '名字',
class_id INT DEFAULT NULL COMMENT '班级id',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_time datetime DEFAULT NULL COMMENT '更新时间',
is_del TINYINT DEFAULT 0 COMMENT '是否已删除,0:否 1: 是',
PRIMARY KEY (`id`)
);
INSERT INTO `student` VALUES (1, '小明', 1, '2022-04-03 15:10:21', '2022-04-03 15:35:06', 0);
INSERT INTO `student` VALUES (2, '小野', 1, '2022-04-03 15:10:21', '2022-04-03 15:35:06', 0);
INSERT INTO `student` VALUES (3, '小王', 2, '2022-04-03 15:10:21', '2022-04-03 15:35:06', 0);
INSERT INTO `student` VALUES (4, '小李', 3, '2022-04-03 15:10:21', '2022-04-03 15:35:06', 0);
book_borrow表
CREATE TABLE book_borrow (
id BIGINT ( 20 ) NOT NULL AUTO_INCREMENT COMMENT '自增id',
book_name VARCHAR ( 50 ) DEFAULT NULL COMMENT '名字',
student_id BIGINT DEFAULT NULL COMMENT '班级id',
student_name VARCHAR ( 30 ) DEFAULT NULL COMMENT '学生名字',
class_id INT DEFAULT NULL COMMENT '班级id',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_time datetime DEFAULT NULL COMMENT '更新时间',
is_del TINYINT DEFAULT 0 COMMENT '是否已删除,0:否 1: 是',
PRIMARY KEY (`id`)
);
INSERT INTO `book_borrow` VALUES (1, 'Spring实战', 1, NULL, NULL, '2022-04-03 15:37:21', '2022-04-03 15:37:24', 0);
INSERT INTO `book_borrow` VALUES (2, 'Spring微服务实战', 88, '88不能被删除', NULL, '2022-04-03 15:37:21', '2022-04-03 15:37:24', 0);
INSERT INTO `book_borrow` VALUES (3, '深入理解Java虚拟机', 3, NULL, NULL, '2022-04-03 15:37:21', '2022-04-03 15:37:24', 0);
INSERT INTO `book_borrow` VALUES (4, 'java编程思想', 99, '99不能被删除', NULL, '2022-04-03 15:37:21', '2022-04-03 15:37:24', 0);
INSERT INTO `book_borrow` VALUES (5, 'java核心技术 卷I', 2, '大湿', NULL, '2022-04-03 15:37:21', '2022-04-03 15:37:24', 0);
解析,不同的更新方式:
1 保留原表数据的更新
只会更新student表中有的数据,student表中查不到的数据,在book_borrow表中还保持不变,不会更新,相当于内连接
update book_borrow br,student st set br.student_name = st.name where br.student_id = st.id;
-- 或者
update book_borrow br inner join student st on br.student_id = st.id set br.student_name = st.name;
更新后的结果
2 全部以右表数据为准
更新结果以student的查询结果为准,student中没有查到的记录会全部被更新为null 相当于外连接
update book_borrow br set student_name = (select name from student where id = br.student_id);
-- 或者
update book_borrow br left join student st on br.student_id = st.id set br.student_name = st.name;
更新后的结果: