当多个字段共同提供唯一 ID 时删除重复行

Remove duplicate rows when multiple fields collectively provide unique ID

我有一个 table 用于历史人口普查数据库,其中四个字段共同标识每个人。这四个字段代表不同级别的政府区域,使 table 看起来像这样:

KOMMNR  KRETSNR BOSTNR  PERSNR  FORNVN      ETTNVN
[mncpl] [area]  [rsdnc] [prsn]  [firstn]    [lastn] ← english
0101    001     0001    001     John        Doe
0101    001     0001    002     Richard     Doe
0101    001     0001    003     Johnny      Doe
0101    001     0002    001     Jane        Doe

可以看出,个人是通过结合城市、地区、住所和人这四个数字(短文本格式)来识别的。个人身份证号码已添加到其他数据库中,但目前正在等待在此数据库中实施。

我目前使用的数据库包含大约 90 万个帖子,我最终得到了约 12,000 个重复项,我需要将其删除。来自 table [T3 3 clean] 的示例:

KOMMNR  KRETSNR BOSTNR  PERSNR  FORNVN          ETTNVN
[mncpl] [area]  [rsdnc] [prsn]  [firstn]        [lastn] ← english
0101    001a    0003    5       Ole Christian   Elingsen
0101    001a    0003    5       Ole Christian   Elingsen
1101    001a    0003    6       Kristian        Johannesen
1101    001a    0003    6       Kristian        Johannesen
2101    001a    0004    14      Jens Tøger      Jensen
2101    001a    0004    14      Jens Tøger      Jensen

我已阅读并查看了 here 提供的答案,但无法理解如何将其应用于我正在使用的结构,原因有二:我们的数据库结合了多个字段来创建每个人的准唯一 ID;由于没有单一的增量数字,我相信我无法应用该优秀答案中提供的方法。

总结

我想要完成的是删除所有重复项。我在本地使用 MS Access 2013 工作。

更新: 由于数据是公开可用的,托管在我们的 Oracle 服务器上,重要的是我在本地所做的事情以后可以被其他人重现。但是,我认为该解决方案也可以直接在 Oracle 上运行并不重要,因为任何想要重现我的发现的人都可以下载数据并在本地运行。

备注

我目前不知道从哪里开始写代码 select 每个副本只有一个,然后删除它们,所以我无法提供示例。我试过 运行 SELECT DISTINCT *,但我以 Access 没有响应而告终;显然有太多数据无法处理这样的查询,即使 运行 它在仅 12k 的缩减样本集上也是如此。

以下是我 select 编辑副本的方式:

SELECT
KOMMNR, KRETSNR, BOSTNR, PERSNR,
NYHUSH, FORNVN, ETTNVN,
BOSTAT, SEDVBO, ANTOPP, BYGNING,
KJONN, FAMST, SIVST, YRKE,
FAAR, FSTED, FSTED_KODE,
STATSB, TROSSMF, SYKDOM, SYKVAR,
BOSTNVN, FORNVNS, ETTNVNS,
PID

FROM [T3 3 FAAR rensket]

WHERE (
    (([T3 3 FAAR rensket].KOMMNR) In (
        SELECT KOMMNR FROM [T3 3 FAAR rensket] As Tmp
      GROUP BY KOMMNR, KRETSNR, BOSTNR, PERSNR HAVING Count(*)>1
           and KRETSNR = [T3 3 FAAR rensket].KRETSNR
           and BOSTNR  = [T3 3 FAAR rensket].BOSTNR
           and PERSNR  = [T3 3 FAAR rensket].PERSNR
        )
    )
)

ORDER BY KOMMNR, KRETSNR, BOSTNR, PERSNR;

这基本上是您的查询:

SELECT r.*
FROM [T3 3 FAAR rensket] as r
WHERE r.KOMMNR In (SELECT KOMMNR
                   FROM [T3 3 FAAR rensket] As r2
                   GROUP BY KOMMNR, KRETSNR, BOSTNR, PERSNR
                   HAVING Count(*) > 1 AND
                          r2.KRETSNR = r.KRETSNR AND
                          r2.BOSTNR  = r.BOSTNR AND
                          r2.PERSNR  = r.PERSNR
                 )
ORDER BY KOMMNR, KRETSNR, BOSTNR, PERSNR;

第一个建议:将关联子句移动到 WHERE 子句:

SELECT r.*
FROM [T3 3 FAAR rensket] as r
WHERE r.KOMMNR In (SELECT r2.KOMMNR
                   FROM [T3 3 FAAR rensket] As r2
                   WHERE r2.KRETSNR = r.KRETSNR AND
                         r2.BOSTNR  = r.BOSTNR AND
                         r2.PERSNR  = r.PERSNR
                   GROUP BY KOMMNR, KRETSNR, BOSTNR, PERSNR
                   HAVING Count(*) > 1
                 )
ORDER BY KOMMNR, KRETSNR, BOSTNR, PERSNR;

其次,在[T3 3 FAAR rensket](KRETSNR, BOSTNR, PERSNR, KOMMNR)上添加索引。

看看这些是否有助于提高性能。

正如@DarrenBartrup-Cook 在评论中所建议的,最简单的方法是执行以下操作:

  1. (创建table结构的副本)[http://www.techrepublic.com/article/copy-an-existing-table-structure-into-a-new-access-database/];
  2. 使KOMMNRKRETSNRBOSTNRPERSNR这四个键成为主键(在设计视图中打开结构table,select 这些键的四行,然后单击主键按钮);
  3. 然后创建追加查询以将数据插入新的 table.

执行这些步骤后,正如所希望的那样,我收到的帖子比原来少了 5926 条 table,不祥地通过错误消息报告。

似乎我得到重复条目的原因——尽管创建了带有大量附加项的 table——是因为我没有任何 actual 主键。没有主键,Access 无法知道两个字段是否相互重复

我 运行 计数以确认结果(由 Karl-Erlend Mikalsen 提供(与@GordonLinoff 建议的解决方案非常相似)):

SELECT x.KOMMNR,
       x.KRETSNR,
       x.BOSTNR,
       x.PERSNR,
       x.antall
FROM ( SELECT A.KOMMNR,
              A.KRETSNR,
              A.BOSTNR,
              A.PERSNR,
              COUNT (*) AS antall
         FROM [T3 3 FAAR rensket] A
     GROUP BY A.KOMMNR,
              A.KRETSNR,
              A.BOSTNR,
              A.PERSNR) AS X
WHERE x.antall > 1;

(注意:这需要一个名为“x”的虚拟 table 才能工作。

正如预期(和深切希望的那样)这产生了 0 个帖子,而相同的查询但最后一行更改为 WHERE x.antall = 1; 产生了预期的 891724 个帖子(与原始 [=40 中的 894262 个帖子相比) =],这是预期的)。