在多个字段上查找重复的行

时间:2011-09-30 16:50:29

标签: mysql duplicates

我正在使用此查询根据两个字段查找重复项:

SELECT 
    last_name, 
    first_name,
    middle_initial,
    COUNT(last_name) AS Duplicates,
    IF(rec_id = '', 1, 0) AS has_REC_ID 
FROM files
GROUP BY last_name, first_name
HAVING COUNT(last_name) > 1 AND COUNT(first_name) > 1;

好的,这返回的是一组包含名字,姓氏和中间名称的行,一个名为'Duplicates'的列,包含大量的2s,以及一个名为has_REC_ID的列,其中包含1和0的混合。

最终,我要做的是找到哪些行具有匹配的名字和姓氏 - 然后对于每个对,找到具有('')作为rec_id的值的行,从具有rec_id的那个中分配rec_id值,然后删除首先具有rec_id的记录。

首先,对于初学者,我会创建一个新列,并执行以下操作:

UPDATE files a 
SET a.has_dup    --new column
    = if(a.last_name IN (
                         SELECT b.last_name
                         FROM files b
                         GROUP BY b.last_name 
                         HAVING COUNT(b.last_name) > 1
                        )
      , 1, null);

但是MySQL返回:“你不能在from子句”

中为更新指定目标表'a'

我敢打赌,这比我在这里尝试的方法更荒谬。有人可以帮我弄清楚那是什么吗?

更新:我也尝试过:

UPDATE files a 
SET a.has_dup = 1
WHERE a.last_name IN (
                         SELECT b.last_name
                         FROM files b
                         GROUP BY b.last_name 
                         HAVING COUNT(b.last_name) > 1
                     );

...并收到相同的错误消息。

3 个答案:

答案 0 :(得分:0)

来自the documentation

  

目前,您无法更新表并从子查询中的同一表中进行选择。

我无法想到快速解决方法。


更新

显然,there is a "quick" workaround,但是它的表现是否是另一个问题。这是通过引入临时表来添加新的间接层:

UPDATE files a 
SET a.has_dup    --new column
    = if(a.last_name IN (
                     SELECT b.last_name
                     FROM
                          (SELECT * FROM files)      -- new table target
                     b
                     GROUP BY b.last_name 
                     HAVING COUNT(b.last_name) > 1
                    ),
      1, null);

答案 1 :(得分:0)

你可以:

1)创建一个保留表

2)使用具有匹配的名字和姓氏的行填充保留表并使用rec_id!=“”

3)删除原始表(文件)中具有匹配的名字和姓氏的行并具有rec_id!=“”

4)更新原始表中具有匹配的名字和姓氏的行,并使用rec_id =“”。

5)放下保持桌

类似于:

create table temp
(
firstname varchar(100) not null,
lastname varchar(100) not null,
rec_id int not null
);


insert into temp (select firstname,lastname,rec_id from files where firstname =    lastname and rec_id != '');


delete from files where firstname = lastname and rec_id != '';

update files f
set f.rec_id = (select t.rec_id from temp t where f.firstname = t.firstname and f.lastname = t.lastname)
where f.firstname = f.lastname 
and f.rec_id != '';


drop table temp;

答案 2 :(得分:-1)

我没有任何MySQL可以测试,但我认为这应该是可行的:(EDITED-> FAIL)

UPDATE files
SET has_dup
    = if(last_name IN (
                         SELECT b.last_name
                         FROM files b
                         GROUP BY b.last_name 
                         HAVING COUNT(b.last_name) > 1
                      )
      , 1, null);

编辑:另一次尝试:

UPDATE files f, (SELECT b.last_name
                   FROM files b
               GROUP BY b.last_name 
                 HAVING COUNT(b.last_name) > 1
                ) as duplicates
   SET f.has_dup = 1
 WHERE f.last_name = duplicates.last_name