比较SQL Server中的10m记录

时间:2015-09-27 19:55:45

标签: sql sql-server-2008

我要求通过(SSN)或(LName&地址)比较1000万个帐户,并找出属于同一个人(SSN)或家庭成员(姓名和地址)的帐户。同一帐户可以有多个联名账户持有人。因此,查询应该是递归的,以获得与每个帐户持有人匹配的帐户+结果帐户应该进一步应用相同的逻辑。

样本表

AccountNo   |   Account Holders|        SSN 
12345678    |   Father         |    3333333333
12345678    |   Mother         |    4444444444

23232323    |   Son            |    5555555555

45454545    |   Father         |    3333333333
45454545    |   Son            |    5555555555
45454545    |   Daughter       |    1111111111

98989898    |   wife           |    1010101010
98989898    |   Son            |    5555555555

名称和地址将有其他列。地址比较逻辑很棘手,因此我使用函数来比较两个地址。

最初我使用游标来处理比较逻辑并获得同一组下的所有匹配帐户。但是,它需要花费太多时间,并且预计会运行几天来处理所有1000万条记录。

我正在努力寻找另一种更快的解决方案。我的第一个方法是让所有帐户与SSN匹配并创建组然后我将尝试名称&地址。

我正在尝试使用CTE来获取群组。因此,对于上面的示例,我希望所有上述帐户在同一个groupid下。并且将有其他家庭具有单独的groupid。

第一件事,我收集了所有具有相同SSN的组。现在我想合并多个SSN持有的所有帐户,现在属于不同的组。

这是我用来通过SSN获取小组的初始CTE

;WITH CTE_SGroup AS
(
    SELECT 
        AccountNo, SSN,
        DENSE_RANK() OVER (ORDER BY SSN) SGROUPID
    FROM 
        AcctTable
)

现在,我无法获得查询以递归方式合并所有这些帐户。

有关此问题的任何帮助都会有所帮助。

其他: 这是示例。我有这个表和第三列预期列。

Acct#   SSNGrp      Expected Result
1       4           1
1       5           1
2       6           1
4       2           1
4       4           1
4       6           1
3       7           2
5       7           2

使用帐户1开始处理,前两行将具有相同的组。现在对于所有SSNGrp 4和5从第二列将导致相同的组。然而,SSNgrp 4也属于Acct#4,因此Acct#4的所有3行被分配给相同的组。递归地,由于SSNgrp 6,Accnt 2也将在第1组中。

2 个答案:

答案 0 :(得分:1)

MIN OVER匹配具有相同值的多个行,使用此结果将此结果分配给现有数据并重复该过程,直到不再更新行为止:

-- untested (modified existing Teradata SQL to SQL Server syntax)
DECLARE @activity_count INTEGER

select *, 
   row_number() over (order by AccountNo) as rn, -- you need a key for the UPDATEs
   row_number() over (order by AccountNo) as GroupNo -- matched rows get the same group
into #temp
from tab

set @activity_count = @@ROWCOUNT

while @activity_count > 0 -- recursive part, repeat until no more row UPDATEd
begin

   update #temp 
   set GroupNo = x.newGrp
   from 
     (select rn, SSN, 
         min(GroupNo) over (partition by SSN) as newGrp -- same SSN
      from #temp
     ) as x
   where #temp.rn = x.rn
     and #temp.GroupNo <> x.newGrp -- only new group members

   set @activity_count = @@ROWCOUNT

   update #temp 
   set GroupNo = x.newGrp
   from 
     (select rn, AccountNo, 
         min(GroupNo) over (partition by AccountNo) as newGrp -- same AccountNo
      from #temp
     ) as x
   where #temp.rn = x.rn
     and #temp.GroupNo <> x.newGrp -- only new group members

   set @activity_count = @activity_count + @@ROWCOUNT

   -- repeat previous UPDATE/SET for any other column to match

end -- while

select dense_rank() over (order by GroupNo) as expectedResult, *
from #temp
order by GroupNo, rn

为了能够包含地址匹配逻辑,您的功能必须将单个地址缩减为简化形式。

答案 1 :(得分:0)

遍历每一行并用光标将其与每一行进行比较将会非常缓慢。为了更容易地找到重复项,我会将它们分组并仅返回带有&gt;的副本。 1组中。这是一个示例:

SELECT AccountNumber, count(1)
FROM foo
GROUP BY AccountNumber
HAVING COUNT(1) > 1

找到重复项后,您就可以开始合并/删除它们了。