0

我有一个包含个人及其一些详细信息的大型数据集。该数据集包含大量重复项,并且大量记录基于它们的特征之一相互“关联”。为确保链接正确的记录,3 个要素中有 2 个的匹配项将被计为一个链接。每个人都需要链接到所有可能的记录,并且每个记录都将被分配一个 clusterId。

我有以下数据集结构:

+--+----+----+----+
|id|col1|col2|col3|
+--+----+----+----+
|1 |A   |B   |C   |
+--+----+----+----+
|2 |A   |B   |D   |
+--+----+----+----+
|3 |A   |Z   |D   |
+--+----+----+----+

id 1 将链接到 id 2(因为 col1 和 col2 相同),id 2 将链接到 id 3(因为 col1 和 col3 相同)。链接 id 1 和 2 为这个“集群”添加了更多信息,并且在建立链接之后,id 3 应该属于该集群。

数据集非常大(2800 万条记录),我没有一个好主意可以让我在合理的时间范围内建立这些关系。

任何想法解决这个问题的最快和最优雅的方法是什么?

4

1 回答 1

0

有了这么多数据,创建关系可能会很慢,但是如果您的列被索引并且您有一个快速的服务器,那么它可能不会太糟糕。创建一个表来存储关系。此 SQL 应填充关系。

CREATE TABLE RelationshipTable
    ([id1] int, [id2] int,[cluster] int);   

INSERT INTO RelationshipTable
    SELECT a.id,b.id,NULL
    FROM TestTable a
    LEFT JOIN TestTable b ON a.id<>b.id AND (
        (
                    ((a.col1 is null and b.col1 is null) or a.col1=b.col1)
                and ((a.col2 is null and b.col2 is null) or a.col2=b.col2)
        )
        OR
        (
                    ((a.col1 is null and b.col1 is null) or a.col1=b.col1)
                and ((a.col3 is null and b.col3 is null) or a.col3=b.col3)
        )
        OR
        (
                    ((a.col2 is null and b.col2 is null) or a.col2=b.col2)
                and ((a.col3 is null and b.col3 is null) or a.col3=b.col3)
        )
    )

DECLARE @UpdateId INT
DECLARE @ClusterId INT
SET @ClusterId=0

WHILE EXISTS(
    SELECT *
    FROM RelationshipTable
    WHERE [cluster] IS NULL
)
BEGIN
  SET @ClusterId=@ClusterId+1

  SELECT
    @UpdateId=[id1]
  FROM RelationshipTable
  WHERE [cluster] IS NULL

  UPDATE RelationshipTable
  SET [cluster]=@ClusterId
  WHERE ID1=@UpdateId
  OR ID2=@UpdateId

  WHILE @@Rowcount>0
  BEGIN
    UPDATE RelationshipTable
    SET [cluster]=@ClusterId
    WHERE [cluster] IS NULL
    AND
    (
      ID1 IN (
           SELECT ID1
           FROM RelationshipTable
           WHERE [cluster]=@ClusterId
           UNION
           SELECT ID2
           FROM RelationshipTable
           WHERE [cluster]=@ClusterId
      )
      OR ID2 IN (
           SELECT ID1
           FROM RelationshipTable
           WHERE [cluster]=@ClusterId
           UNION
           SELECT ID2
           FROM RelationshipTable
           WHERE [cluster]=@ClusterId
      )
    )
  END
END

select * from RelationshipTable
于 2013-02-05T13:27:19.870 回答