先看牛客网的题目:删除emp_no重复的记录,只保留最小的id对应的记录
题目用到的表结构和测试数据(因为已经有人写过这个文章,所以前面题目与他的高度相似,这是没办法,题目相同,测试用例也是一样。所以我改了一些测试用例的参数,所以与截图返回的结果不一样,希望看到这篇文章的人可以见谅。希望可以标志我的为原创!):
CREATE TABLE IF NOT EXISTS titles_test (
id int(11) not null primary key,
emp_no int(11) NOT NULL DEFAULT '',
title_name varchar(50) NOT NULL DEFAULT '',
fromdate date NOT NULL DEFAULT '',
todate date DEFAULT NULL DEFAULT '');
insert into titles_test values ('1', '12121', 'manager', '1981-01-29', '9999-01-01'),
('2', '12122', 'CEO', '1982-12-02', '9999-01-01'),
('3', '12123', 'manager', '1975-02-12', '9999-01-01'),
('4', '12124', 'manager', '1998-11-23', '9999-01-01'),
('5', '12125', 'manager', '1988-09-12', '9999-01-01'),
('6', '12126', 'CEO', '1999-02-11', '9999-01-01'),
('7', '12127', 'manager', '1999-11-13', '9999-01-01');
这时候,我们的表中已经有7条数据。我们发现,测试数据中,相同的数据id分别是1,2,3,5,6,7
解题思路:我们可以使用GROUP BY ,HAVING先把重复的id查找出来,SQL如下:
SELECT
id
FROM
titles_test
GROUP BY
emp_no
HAVING
count( emp_no ) > 1;
我们会发现,查找的结果是
虽然这样子,也可以进行下一步操作,然后把重复的数据删除,最后只保留id为4,5,6,7的数据,但是这样子却与题目不相符。所以,我们需要把id值为5,6,7的重复数据查找出来,然后再去删除对应id的数据,才能满足需要,那么我们只需要加上MAX()函数即可。SQL语句如下:
SELECT
MAX( id ) AS id
FROM
titles_test
GROUP BY
emp_no
HAVING
COUNT( emp_no ) > 1
结果如下:
最后我们使用DELTE FROM table WHERE [condition]语句即可。
这是错误执行语句
DELETE
FROM
titles_test
WHERE
id IN ( SELECT MAX( id ) AS id FROM titles_test GROUP BY emp_no HAVING COUNT( emp_no ) > 1 )
报错:1093 - You can’t specify target table ‘titles_test’ for update in FROM clause。
原因是:不能先select出同一表中的某些值,再update这个表(在同一语句中)
或者这样子去理解更好:更新这个表的同时又查询了这个表,查询这个表的同时又去更新了这个表,可以理解为死锁。mysql不支持这种更新查询同一张表的操作
因此我们需要修改一下执行语句:
这是正确的执行语句
DELETE FROM
titles_test
WHERE
id IN (
SELECT
a.id
FROM
(
SELECT
max( id ) AS id
FROM
titles_test
GROUP BY
emp_no
HAVING
count( emp_no ) > 1 )
AS a
)
这个时候,我们发现结果就是符合题目要求了。