如何删除一条 table 中的重复项,但只保留一条记录?
How to delete duplicates from one table, but keeping only one record?
您好SQL查询专家!
我有一个名为 'mytable' 的 table,它有 2 列,例如 id 和 title 。
我试图删除重复项,但只有一个记录(行)比较标题。
以下是我的选择:
DELETE FROM `myTable` AS `m1`
WHERE `m1`.`id`
NOT IN (SELECT MIN(`b`.`id`) as `recordid` FROM `myTable` AS `b` GROUP BY `b`.`title`)
错误:Error in query (1064): Syntax error near '* FROM `myTable` AS `m1` WHERE `m1`.`id` NOT IN (SELECT MIN(`b`.`id`) as `reco' at line 1
但我遇到了麻烦,并试图解决这个问题超过 2 小时。
这似乎是一个非常简单的问题。
但我想不通。所以我要求计算器!
主要是,我看到了一些奇怪的东西。
我这样试过,但没有任何错误。
SELECT * FROM `myTable` AS `m1`
WHERE `m1`.`id`
NOT IN (SELECT MIN(`b`.`id`) as `recordid` FROM `myTable` AS `b` GROUP BY `b`.`title`)
当我 运行 这个查询时,我可以从 'myTable' table.
中获取要删除的记录(行)列表
为什么我可以获取到要删除的列表,却出现删除问题?
我真的需要你的帮助。
谢谢大家!
您可以这样表述:
delete m
from mytable m left join
(select m2.title, min(m2.id) as min_id
from mytable m2
group by m2.title
) m2
on m.title = m2.title and m.id > m.min_id;
为了提高性能,您需要在 (title, id)
上建立索引。
我认为戈登的回答抓住了要点。最近不得不做类似的事情,结果是这样的(适用于您的情况):
DELETE FROM mytable WHERE id IN (
SELECT *
FROM (
SELECT m.id
FROM my_table m
WHERE m.id NOT IN (
SELECT MAX(m.id)
FROM my_table sub
GROUP BY sub.title
HAVING COUNT(sub.title) > 1
)
AND m.id NOT IN (
SELECT MAX(sub2.id)
FROM my_table sub2
GROUP BY sub2.title
HAVING COUNT(sub2.title) = 1
)
) AS m
)
额外的包装器是必要的(如果我没记错的话)因为 sub-query 在 DELETE 语句中是不允许的(但可以像所示那样使用)。
这将按 ID 删除所有计数(title
)大于 0 的记录,但不会删除最新的(max
)记录。
注意:这是一个非常密集的查询。建议在 ID 和标题上建立索引,即便如此:sloooowwww。 运行 这仅需要 10 万条带索引的记录,但仍需要大约 10 秒。
语法:
DELETE FROM `myTable` AS `m1`
错了。
应该是:
DELETE m1 FROM `myTable` AS `m1`
但您不需要为 table 添加别名,您可以这样做
DELETE FROM `myTable`
此外 MySql 不允许在子查询中直接使用目标 table,就像您使用 NOT IN
一样,但是您可以通过包含子查询来克服此限制在另一个里面:
DELETE FROM `myTable`
WHERE `id` NOT IN (
SELECT `recordid`
FROM (
SELECT MIN(`id`) as `recordid`
FROM `myTable`
GROUP BY `title`
) t
)
我删除了嵌套子查询的别名,因为不需要它们。
我终于找到了问题的确切原因。
我引用了@Malakiyasanjay 的评论。
你可以从这里找到 How to keep only one row of a table, removing duplicate rows?
我这样试过:(它对我也有效,但是 运行 查询 30,000 行花了很多时间)
delete from myTable
where id not in
(select min(id) as min from (select * from myTable) as x group by title)
问题是我无法将“myTable”table 指定为目标 table。所以我使用 (select * from myTable) as x
并弄明白了。
抱歉,我无法解释更多细节,因为我不熟悉 mysql 查询。但你应该注意:
MySql does not allow the direct use of the target table inside a subquery like the one you use with NOT IN, but you can overcome this limitation by enclosing the subquery inside another one.
(Please reference @forpas 's answer.)
但是你要注意这需要很长时间...这可能会导致超时错误。我 运行 这个关于 table 的查询有大约 600,000 行,但几天没有响应。所以我得出结论,这个想法非常适合小型数据库 table.
希望对大家有所帮助! :)
您好SQL查询专家! 我有一个名为 'mytable' 的 table,它有 2 列,例如 id 和 title 。 我试图删除重复项,但只有一个记录(行)比较标题。 以下是我的选择:
DELETE FROM `myTable` AS `m1`
WHERE `m1`.`id`
NOT IN (SELECT MIN(`b`.`id`) as `recordid` FROM `myTable` AS `b` GROUP BY `b`.`title`)
错误:Error in query (1064): Syntax error near '* FROM `myTable` AS `m1` WHERE `m1`.`id` NOT IN (SELECT MIN(`b`.`id`) as `reco' at line 1
但我遇到了麻烦,并试图解决这个问题超过 2 小时。
这似乎是一个非常简单的问题。
但我想不通。所以我要求计算器!
主要是,我看到了一些奇怪的东西。 我这样试过,但没有任何错误。
SELECT * FROM `myTable` AS `m1`
WHERE `m1`.`id`
NOT IN (SELECT MIN(`b`.`id`) as `recordid` FROM `myTable` AS `b` GROUP BY `b`.`title`)
当我 运行 这个查询时,我可以从 'myTable' table.
中获取要删除的记录(行)列表为什么我可以获取到要删除的列表,却出现删除问题?
我真的需要你的帮助。 谢谢大家!
您可以这样表述:
delete m
from mytable m left join
(select m2.title, min(m2.id) as min_id
from mytable m2
group by m2.title
) m2
on m.title = m2.title and m.id > m.min_id;
为了提高性能,您需要在 (title, id)
上建立索引。
我认为戈登的回答抓住了要点。最近不得不做类似的事情,结果是这样的(适用于您的情况):
DELETE FROM mytable WHERE id IN (
SELECT *
FROM (
SELECT m.id
FROM my_table m
WHERE m.id NOT IN (
SELECT MAX(m.id)
FROM my_table sub
GROUP BY sub.title
HAVING COUNT(sub.title) > 1
)
AND m.id NOT IN (
SELECT MAX(sub2.id)
FROM my_table sub2
GROUP BY sub2.title
HAVING COUNT(sub2.title) = 1
)
) AS m
)
额外的包装器是必要的(如果我没记错的话)因为 sub-query 在 DELETE 语句中是不允许的(但可以像所示那样使用)。
这将按 ID 删除所有计数(title
)大于 0 的记录,但不会删除最新的(max
)记录。
注意:这是一个非常密集的查询。建议在 ID 和标题上建立索引,即便如此:sloooowwww。 运行 这仅需要 10 万条带索引的记录,但仍需要大约 10 秒。
语法:
DELETE FROM `myTable` AS `m1`
错了。
应该是:
DELETE m1 FROM `myTable` AS `m1`
但您不需要为 table 添加别名,您可以这样做
DELETE FROM `myTable`
此外 MySql 不允许在子查询中直接使用目标 table,就像您使用 NOT IN
一样,但是您可以通过包含子查询来克服此限制在另一个里面:
DELETE FROM `myTable`
WHERE `id` NOT IN (
SELECT `recordid`
FROM (
SELECT MIN(`id`) as `recordid`
FROM `myTable`
GROUP BY `title`
) t
)
我删除了嵌套子查询的别名,因为不需要它们。
我终于找到了问题的确切原因。 我引用了@Malakiyasanjay 的评论。 你可以从这里找到 How to keep only one row of a table, removing duplicate rows?
我这样试过:(它对我也有效,但是 运行 查询 30,000 行花了很多时间)
delete from myTable
where id not in
(select min(id) as min from (select * from myTable) as x group by title)
问题是我无法将“myTable”table 指定为目标 table。所以我使用 (select * from myTable) as x
并弄明白了。
抱歉,我无法解释更多细节,因为我不熟悉 mysql 查询。但你应该注意:
MySql does not allow the direct use of the target table inside a subquery like the one you use with NOT IN, but you can overcome this limitation by enclosing the subquery inside another one. (Please reference @forpas 's answer.)
但是你要注意这需要很长时间...这可能会导致超时错误。我 运行 这个关于 table 的查询有大约 600,000 行,但几天没有响应。所以我得出结论,这个想法非常适合小型数据库 table.
希望对大家有所帮助! :)