如何在同一个表上更新具有不同值的多个重复项?

时间:2013-08-08 23:17:15

标签: mysql sql join duplicates

我正在处理的表格有多行,latlon的值相同。该示例显示135具有相同的位置,但name属性不同。 hashnamelatlon构建,因此不同。

BEFORE:

 id | name | lat | lon | flag | hash
----+------+-----+-----+------+------
 1  | aaa  | 16  | 48  |  0   | 2cd       <-- duplicate
 2  | bbb  | 10  | 22  |  0   | 3fc
 3  | ccc  | 16  | 48  |  0   | 8ba       <-- duplicate
 4  | ddd  | 10  | 23  |  0   | c33
 5  | eee  | 16  | 48  |  0   | 751       <-- duplicate

我需要在此表中标识“重复”,并希望将标记1)分配给其中一个标记2次要)给其他人。将“复制”标记为 primary 并不重要。

 AFTER:

 id | name | lat | lon | flag | hash
----+------+-----+-----+------+------
 1  | aaa  | 16  | 48  |  1   | 2cd       <-- updated
 2  | bbb  | 10  | 22  |  0   | 3fc
 3  | ccc  | 16  | 48  |  2   | 8ba       <-- updated
 4  | ddd  | 10  | 23  |  0   | c33
 5  | eee  | 16  | 48  |  2   | 751       <-- updated

我开始尝试INNER JOIN inspired by this post和此visual description。有了这个,我可以为所有重复项分配相同的标志。

UPDATE table t1
INNER JOIN table_name t2
ON
  t1.lat = t2.lat
  AND t1.lon = t2.lon
  AND t1.hash != t2.hash
SET
  t1.flag = 2;

我还使用LEFT OUTER JOIN测试了WHERE t2.id IS NULL,当只有两行时,它可以正常工作。但是,我无法想象JOIN应如何处理多于两个重复。 Mark Harrison还假设“您正在加入没有重复的列” at the beginning of his post,这听起来好像这不是一个好主意。

如果感兴趣,我正在使用MySQL。

3 个答案:

答案 0 :(得分:2)

不确定这是非常有效的,但works in just one query

UPDATE t
JOIN (
  SELECT MAX(t.id) AS maxid, lat, lon
  FROM t
  JOIN t AS duplicates
  USING (lat, lon)
  GROUP BY lat, lon
  HAVING COUNT(*) > 1
) AS maxima USING (lat, lon)
SET flag = IF(id = maxid, 1, 2);

答案 1 :(得分:0)

假设您希望所有规范记录都有flag=1(而不仅仅是那些具有重复记录的记录),您可以这样做:

UPDATE table t1
SET t1.flag = 1
WHERE t1.id in (
    SELECT min(id)
    FROM table t2
    WHERE t1.lat = t2.lat
    AND t1.lon = t2.lon
);

UPDATE table
SET flag = 2
WHERE flag is null;

COMMIT;

答案 2 :(得分:0)

您可以分两步完成此操作:

update table t1 set flag = 2 where id in 
   (select a.id
    from 
        t1 a
        join t1 b on (b.lon = a.lon and b.lat = a.lat));

update table t1 set flag = 1 where id in 
   (select a.id 
    from t1 a
    where a.flag = 2 and a.id = 
        (select min(b.id) from t1 b where b.lon = a.lon and b.lat = a.lat)
   );

这应该被用作灵感,不是作为福音(可能是错的):)