Mysql 使用自定义逻辑删除重复行
我一直在寻找一种方法,使用一些自定义逻辑删除MySQL数据库中的一些重复行 实际数据:Mysql 使用自定义逻辑删除重复行,mysql,duplicates,Mysql,Duplicates,我一直在寻找一种方法,使用一些自定义逻辑删除MySQL数据库中的一些重复行 实际数据: id name population 1 CityA 1000 2 CityA 50 3 CityA 0 4 CityB 0 5 CityB 0 6 CityC 10 预期结果: id name population 1 CityA 1000 4 CityB 0 6 CityC 10 我尝试了这个查询,但没有成功(如果
id name population
1 CityA 1000
2 CityA 50
3 CityA 0
4 CityB 0
5 CityB 0
6 CityC 10
预期结果:
id name population
1 CityA 1000
4 CityB 0
6 CityC 10
我尝试了这个查询,但没有成功(如果所有人口都等于0
,它已删除了一个城市的所有行,如CityB示例中所示):
删除t
从表t到表t2
t.id!=t2.id
和t.population您可以使用子查询进行连接,该子查询返回每个城市人口最多的行的ID
DELETE t1
FROM YourTable AS t1
JOIN (SELECT name, MAX(id) AS maxid
FROM YourTable AS t2
JOIN (SELECT name, MAX(population) AS maxpop
FROM YourTable
GROUP BY name) AS t3
ON t2.name = t3.name AND t2.population = t3.maxpop
GROUP BY t2.name) AS t4
ON t1.name = t4.name AND t1.id != t4.maxid
我需要额外的子查询嵌套级别,因为一个名称有多个具有相同填充的行。因此,它首先需要获取每个名称的最大人口,然后使用max(ID)
在该组中选择一个特定ID。您可以使用子查询进行连接,该子查询返回每个城市人口最多的行的ID
DELETE t1
FROM YourTable AS t1
JOIN (SELECT name, MAX(id) AS maxid
FROM YourTable AS t2
JOIN (SELECT name, MAX(population) AS maxpop
FROM YourTable
GROUP BY name) AS t3
ON t2.name = t3.name AND t2.population = t3.maxpop
GROUP BY t2.name) AS t4
ON t1.name = t4.name AND t1.id != t4.maxid
我需要额外的子查询嵌套级别,因为一个名称有多个具有相同填充的行。因此,它首先需要获得每个名称的最大人口,然后在该组中选择一个特定的ID,该ID的max(ID)
看起来像是要在名称
列中“匹配”城市
在将SELECT语句转换为DELETE语句之前,先编写并测试SELECT语句
SELECT d.*
FROM table d
JOIN table k
ON k.name = d.name
AND k.population > d.population
AND k.id <> d.id
内联视图q
应该从我们想要保留的行返回id
值的列表。任何具有id
但不在该列表中的行都是我们要删除的行
如果MySQL对内联视图中的表引用犹豫不决,我们可以将其包装到另一个内联视图中作为解决方法
SELECT d.*
FROM table d
LEFT
JOIN ( SELECT q.min_id
FROM ( SELECT MIN(r.id) AS min_id
FROM ( SELECT t.name
, MAX(t.population) AS max_pop
FROM table t
GROUP BY t.name
) s
JOIN table r
ON r.name = s.name
AND r.population = s.max_pop
GROUP BY r.name
) q
) p
ON p.min_id = d.id
WHERE p.min_id IS NULL
通过将最外层的SELECT关键字替换为DELETE关键字,将其转换为DELETE语句。看起来您希望在名称
列中对城市进行“匹配”
CREATE TABLE new_table (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30),
population INT
);
INSERT INTO new_table (name, population)
SELECT old.name, MAX(old.population)
FROM current_table old
GROUP BY old.name;
RENAME TABLE current_table TO archive_table
, new_table TO current_table;
在将SELECT语句转换为DELETE语句之前,先编写并测试SELECT语句
SELECT d.*
FROM table d
JOIN table k
ON k.name = d.name
AND k.population > d.population
AND k.id <> d.id
内联视图q
应该从我们想要保留的行返回id
值的列表。任何具有id
但不在该列表中的行都是我们要删除的行
如果MySQL对内联视图中的表引用犹豫不决,我们可以将其包装到另一个内联视图中作为解决方法
SELECT d.*
FROM table d
LEFT
JOIN ( SELECT q.min_id
FROM ( SELECT MIN(r.id) AS min_id
FROM ( SELECT t.name
, MAX(t.population) AS max_pop
FROM table t
GROUP BY t.name
) s
JOIN table r
ON r.name = s.name
AND r.population = s.max_pop
GROUP BY r.name
) q
) p
ON p.min_id = d.id
WHERE p.min_id IS NULL
通过将最外层的SELECT关键字替换为DELETE关键字,将其转换为DELETE语句
CREATE TABLE new_table (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30),
population INT
);
INSERT INTO new_table (name, population)
SELECT old.name, MAX(old.population)
FROM current_table old
GROUP BY old.name;
RENAME TABLE current_table TO archive_table
, new_table TO current_table;
一旦你检查了数据
DROP TABLE archive_table;
一旦你检查了数据
DROP TABLE archive_table;
如果有多个同名且人口最多,则需要保留全部或仅保留一行?在这种情况下,我只想保留一行(不考虑所选行)如果有多个同名且人口最多,则需要保留全部或仅保留一行?在这种情况下,我只想保留一行(不考虑所选行)关于“不同的方法”,请参阅我的答案。@spencer7593:非常感谢您的帮助。然而,我专注于Barmar解决方案,它只是起了作用;-)关于“不同的方法”,请参阅我的答案。@spencer7593:非常感谢您的帮助。然而,我专注于Barmar解决方案,它只是起了作用;-)如果有外键指向此表的其他表,则ID将随之更改。虽然DELETE
方法也可能有问题,因为删除相关行时它们将变得无效。如果Guillame的数据库中有数百万行,那么就地删除会导致锁定问题。但我怀疑两者都不适用。这是geonames数据库,因此可能有数百万行。是的,如果有外键指向此表的其他表,则ID将因此改变。虽然DELETE
方法也可能有问题,因为删除相关行时它们将变得无效。如果Guillame的数据库中有数百万行,那么就地删除会导致锁定问题。但我怀疑两者都不适用。这是geonames数据库,所以可能有数百万行。我刚刚尝试了你的解决方案,它删除了所有行;p@GuillaumeSTLRspencer7593是正确的,我修复了查询。@spencer7593正确。另一种方法是使用WHERE id NOT IN(返回所有maxid的子查询)
@Barmar:或者我们可以使用反连接。删除所有行,除了那些id与要保留的id值列表中的行匹配的行。是的,这是我通常使用的模式。但这个查询已经够复杂了。:)我刚刚尝试了你的解决方案,它已经删除了所有的行;p@GuillaumeSTLRspencer7593是正确的,我修复了查询。@spencer7593正确。另一种方法是使用WHERE id NOT IN(返回所有maxid的子查询)
@Barmar:或者我们可以使用反连接。删除所有行,除了那些id与要保留的id值列表中的行匹配的行。是的,这是我通常使用的模式。但这个查询已经够复杂了。:)