MYSQL如何在连字符后根据匹配项删除重复项

问题描述

我的表中有一个名称列表,如下所示:

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的地方。