使用自定义逻辑删除重复行

时间:2017-06-01 20:20:32

标签: 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

我尝试了这个查询但没有成功(如果所有人口都等于0,它已删除了城市的所有行,就像在CityB示例中一样):

DELETE t 
FROM table AS t, table AS t2
WHERE t.id != t2.id
AND t.population <= t2.population

任何超级英雄都可以解决这个超级问题吗?

[编辑]工作解决方案http://sqlfiddle.com/#!9/ea3e3/2

3 个答案:

答案 0 :(得分:2)

您可以使用子查询进行联接,该子查询返回每个城市人口最多的行的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。

答案 1 :(得分:1)

看起来你想&#34;匹配&#34;在name列中的城市。

首先编写一个SELECT语句,然后在将其转换为DELETE语句之前对其进行测试。

SELECT d.*
  FROM table d
  JOIN table k
    ON k.name        = d.name 
   AND k.population  > d.population 
   AND k.id         <> d.id

我们希望保留k中的行,并从d中删除该行。

将SELECT关键字替换为DELETE。将其转换为DELETE语句。

请注意,如果有多个行具有相同的&#34;最高&#34;一个城市的人口,这个查询不会识别那些。摆脱&#34;重复&#34;在人口价值相同的情况下,我们需要采用略有不同的方法。

我使用反加入:

SELECT d.*
  FROM table d
  LEFT
  JOIN ( 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
    ON q.min_id = d.id
 WHERE q.min_id IS NULL

内联视图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语句。

答案 2 :(得分:0)

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;
相关问题