问题描述
paul-jones
Ron-Thomas
John-Doe
Michael-Adams
Jim-Jones
Adam-Jones
Bob-Thomas
Bill-Thomas
我想删除hypen之后姓氏重复的所有行,但想保留每个姓氏最旧的行。 例如,在上述数据集中,我想删除
Jim-Jones
Adam-Jones
Bob-Thomas
Bill-Thomas
并保留
paul-jones
Ron-Thomas
John-Doe
Michael-Adams
以此类推。
我发现下面的查询像这样在连字符后提取所有字符
select SUBSTRING_INDEX(full_name,'-',-1) from names;
,但无法弄清楚如何使用这些值更新表中的last_name列,因此我可以使用此查询基于last_name列中的唯一值进行删除
("ALTER IGnorE TABLE names ADD UNIQUE (`last_name`)") ;
我希望这清楚地解释了我的问题。 感谢您的帮助。
解决方法
您可以在UPDATE查询中使用SUBSTRING_INDEX
来更新last_name
。
UPDATE product
SET last_name = SUBSTRING_INDEX(supplier_reference,'-',-1)
WHERE SUBSTRING_INDEX(supplier_reference,-1) != ''
AND last_name = '';
WHERE
子句将确保仅当连字符后有一个值时,查询才会更新姓氏。
然后,如果要删除重复的行,但保留基于last_name
的最旧的行,
DELETE FROM product
WHERE id NOT IN (
SELECT MIN(id)
FROM product
GROUP BY last_name
)
如果您具有自动递增的值id
,则MIN(id)
将确保保留最旧的记录。要进行测试,请尝试使用DELETE
而不是SELECT * FROM product
来验证这些是否是要删除的记录。
请注意,此查询还将删除last_name
为空的重复行。如果您不希望这样做,请在子查询中添加子句WHERE last_name != ''
。
您不需要单独的last_name列(尽管最好在当前列中包含姓和名列 ),您可以按原样删除:
create table names (id int not null primary key auto_increment,name varchar(63),order_column int not null);
insert into names (name,order_column) values ('Paul-Jones',1),('Ron-Thomas',2),('John-Doe',3),('Michael-Adams',4),('Jim-Jones',5),('Adam-Jones',6),('Bob-Thomas',7),('Bill-Thomas',8);
delete n2 from names n1
join names n2 on
instr(n1.name,'-') and
instr(n2.name,'-') and
substring_index(n1.name,-1)=substring_index(n2.name,-1) and
n2.id<>n1.id and
n2.order_column>n1.order_column;
听起来您有一些日期或其他东西可以识别最早的记录;使用我有order_column的地方。