MYSQL 如何根据连字符后的匹配项删除重复项
MYSQL how to delete duplicates based on match after a hyphen
我的 table 中有一个姓名列表,如下所示:
paul-jones
Ron-Thomas
John-Doe
Michael-Adams
Jim-Jones
Adam-Jones
Bob-Thomas
Bill-Thomas
我想删除连字符后面的姓氏重复的所有行,但想为每个姓氏保留最旧的行。
例如在上面的数据集中我想删除
Jim-Jones
Adam-Jones
Bob-Thomas
Bill-Thomas
并保持
paul-jones
Ron-Thomas
John-Doe
Michael-Adams
等等。
我发现下面的查询可以像这样提取连字符后的所有字符
select SUBSTRING_INDEX(full_name,'-',-1) from names;
但无法弄清楚如何使用这些值更新我的 table 中的 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
)
如果您有 auto-incremented 值 id
那么 MIN(id)
将确保保留最旧的记录。要进行测试,请尝试 SELECT * FROM product
而不是 DELETE
并验证这些是否是您要删除的记录。
请注意,此查询还将删除 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.
我的 table 中有一个姓名列表,如下所示:
paul-jones
Ron-Thomas
John-Doe
Michael-Adams
Jim-Jones
Adam-Jones
Bob-Thomas
Bill-Thomas
我想删除连字符后面的姓氏重复的所有行,但想为每个姓氏保留最旧的行。 例如在上面的数据集中我想删除
Jim-Jones
Adam-Jones
Bob-Thomas
Bill-Thomas
并保持
paul-jones
Ron-Thomas
John-Doe
Michael-Adams
等等。
我发现下面的查询可以像这样提取连字符后的所有字符
select SUBSTRING_INDEX(full_name,'-',-1) from names;
但无法弄清楚如何使用这些值更新我的 table 中的 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
)
如果您有 auto-incremented 值 id
那么 MIN(id)
将确保保留最旧的记录。要进行测试,请尝试 SELECT * FROM product
而不是 DELETE
并验证这些是否是您要删除的记录。
请注意,此查询还将删除 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.