当多个字段共同提供唯一 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 在评论中所建议的,最简单的方法是执行以下操作:
- (创建table结构的副本)[http://www.techrepublic.com/article/copy-an-existing-table-structure-into-a-new-access-database/];
- 使
KOMMNR
、KRETSNR
、BOSTNR
和PERSNR
这四个键成为主键(在设计视图中打开结构table,select 这些键的四行,然后单击主键按钮);
- 然后创建追加查询以将数据插入新的 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 个帖子相比) =],这是预期的)。
我有一个 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 在评论中所建议的,最简单的方法是执行以下操作:
- (创建table结构的副本)[http://www.techrepublic.com/article/copy-an-existing-table-structure-into-a-new-access-database/];
- 使
KOMMNR
、KRETSNR
、BOSTNR
和PERSNR
这四个键成为主键(在设计视图中打开结构table,select 这些键的四行,然后单击主键按钮); - 然后创建追加查询以将数据插入新的 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 个帖子相比) =],这是预期的)。