我有一个要尝试消除重复的组织列表。每个组织最多可以在三个不同领域拥有三个标识号。目前我可以使用的工具是 Oracle SQL 数据库和 SAP Data Services。
Name |ID1 |ID2 |ID3
------|--------|--------|--------
Org1 |1 |<null> |2
Org2 |<null> |1 |<null>
Org3 |2 |<null> |<null>
所有这三个组织都应该能够被识别为一个组织。
第一种方法
解决这个问题的第一个方法是将其分解为组织和 ID 的有序列表。
Name |ID
------|-------
Org1 |1
Org2 |1
Org1 |2
Org3 |2
从那时起,我设法使用数据转换组合来创建仅重复 ID 的列表,其中涉及仅选择可能的 ID 列表、对它们进行排序、删除唯一 ID、为每个 ID 分配一个 ROW_ID(表示作为本示例中的一封信,即使它看起来多余)。
ID |Duplicate_Group
------|--------
1 |A
2 |B
但是如果我将其加入到我的数据中,它并不能解决我的问题。它只会导致进一步的重复。在我意识到我们的组织可以有多个 ID 之前,我最初接受了本类(class)作为我的解决方案:
Name |ID1 |ID2 |ID3 |Duplicate_Group
------|--------|--------|--------|--------
Org1 |1 |<null> |2 |A
Org1 |1 |<null> |2 |B
Org2 |<null> |1 |<null> |A
Org3 |2 |<null> |<null> |B
新方法
我的下一个想法是类似地分配字母来区分我的组织之间的组,但是......循环数据。
Name |ID |Duplicate_Group
------|--------|--------
Org1 |1 |A
Org1 |2 |B
Org2 |1 |A
Org3 |2 |B
首先,按名称、ID 排序,我会检查名称或 ID 是否与前一行相同,然后采用该重复组作为您自己的组。
Name |ID |D_Grp1 |D_Grp2
------|--------|--------|--------
Org1 |1 |A |
Org1 |2 |B |A
Org2 |1 |A |
Org3 |2 |B |
请注意,第二行中 Org1 的 D_Grp2 已更改。现在,我将把旧的 D_Grp1 合并到 D_Grp2 中,然后再做一次——按 ID 顺序,然后是名称;然后再次根据上一行更新组。
Name |ID |D_Grp2 |D_Grp3
------|--------|--------|--------
Org1 |1 |A |
Org2 |1 |A |
Org1 |2 |A |
Org3 |2 |B |A
由于第四行的 ID 与上面相同,但具有不同的 D_Grp2,因此第四行将更新其 D_Grp3 以匹配。我的想法是,我会一遍又一遍地循环这个按 ID 和名称排序的过程,直到不再需要进行更改。我将使某种列或变量充当标志 - 在每次循环之后,如果标志没有勾选,我将假设所有内容都已合并。我将应用一个不同的并将其打回到原始表中。
Name |ID1 |ID2 |ID3 |Duplicate_Group
------|--------|--------|--------|--------
Org1 |1 |<null> |2 |A
Org2 |<null> |1 |<null> |A
Org3 |2 |<null> |<null> |A
就范围而言,我有大约 60,000 个组织,因此循环并非不可能,但它让我感到恶心,需要很长时间,而且似乎无法设计更好的流程。我也不太确定我是否错过了任何边缘情况,即按名称和 ID 排序可能永远不会合并记录。
结论
那么StackOverflow,有没有更好的方法来识别这个表中的重复项?我可以接受任何答案,包括 SQL。请理解 SAP Data Services 的逻辑基本上是 SQL,但我不是直接编写自己的 SQL - 因此到目前为止我无法提供我的流程的 SQL 版本。
最佳答案
这绝对是一个迭代过程,因此需要递归查询。
一定是在寻找链式店。如果 ID 1 = 2、2 = 3、4 = 5、5 = 6、2 = 5,则所有这些 ID 都表示同一家公司。
这是我的算法:
- 查找所有对 1 = 2, 2 = 1, 2 = 3, ...
- 查找所有链(对于 ID 1:1=2=3、1=2=5,对于 ID 2:2=1、2=3、2=5 对于 ID 3:3=2=1、3= 2=5, ...) 并将调用 ID 作为链号赋予链中的所有 ID。 (因此 ID 3 的链号为 1(来自第一条链)、2(来自第四条链)、3(来自第六条和第七条链)。)
- 通过将每个 ID 与其最小链号相关联来构建组。 (因此,ID 3 的链号为 1;ID 3 属于组“chain=1”。)具有相同最小链号的所有 ID 代表同一家公司。
这是查询:
with pairs as
(
select id1 as id, id2 as other from mytable where id1 <> id2
union all
select id1 as id, id3 as other from mytable where id1 <> id3
union all
select id2 as id, id1 as other from mytable where id2 <> id1
union all
select id2 as id, id3 as other from mytable where id2 <> id3
union all
select id3 as id, id1 as other from mytable where id3 <> id1
union all
select id3 as id, id2 as other from mytable where id3 <> id2
)
, chains(chain, id) as
(
select id as chain, id from pairs
union all
select c.chain, p.other as id
from chains c
join pairs p on p.id = c.id
)
cycle chain, id set cycle to 1 default 0
, groups as
(
select id, min(chain) as grp
from chains
group by id
)
select distinct g.grp, m.*
from groups g
join mytable m on g.id in (m.id1, m.id2, m.id3)
order by g.grp, m.name;
当您有很多表示同一家公司的 ID(即要评估很多链)时,此查询可能会非常慢。如果这种情况发生的次数很少(看起来可能性更大),那么查询将会非常快。试试吧:-)
关于sql - 我应该如何识别每条记录可能有多个身份的重复项组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43625826/