如何使用多个字段从表中提取重复记录?

时间:2009-04-03 15:44:47

标签: sql sql-server tsql

我已经查看了Deleting duplicate records using a temporary table这个问题,但这并不足以帮助我解决这个问题:

我在 SQL 2000 Server 上托管了大约200,000个地址位置的表格。由于多年来各方的无效输入导致表格中出现重复数据,因此该表存在巨大问题。我需要输出一个重复记录列表,这样我才能开始清理它们的漫长过程。

请考虑以下表格结构:

Table Company(   
  CompanyId NVarChar(10) Not Null Constraint PK_Locations Primary Key,   
  CompanyName NVarChar(30),   
  CompanyAddress NVarChar(30),   
  CompanyCity NVarchar(30), 
  CompanyState Char(2),   
  CompanyZip NVarChar(10),   
  DateCreated DateTime, 
  LastModified DateTime,  
  LastModifiedUser NVarChar(64) 
)

对于第一个解析我甚至不会担心拼写错误和拼写的变化,这将是一个更大的噩梦,我甚至还没有得到解决的第一个线索。

因此,对于此部分,当多个记录在以下条件下匹配时,记录被视为重复:

  

(CompanyName或CompanyAddress)和CompanyCity And CompanyState

Zip被排除在外,因为很多地方都缺少邮政编码和邮政编码,而且很多都输入不正确,如果我将它们包括在内,它只会使报告的准确性低得多。

我意识到在一个城市/州内的公司可能合法地存在多个地点[例如麦当劳,只是在我的头顶],并且在一个城市内的单个地址可能合法地存在多家公司。国家[例如在购物中心或办公楼内],但目前我们会认为这些至少保证了人们的一定程度的关注,并将其纳入报告中。

单个字段上的匹配是小菜一碟,但是当我到达多个字段时,我就会失败,特别是当有些字段是有条件的时候。

3 个答案:

答案 0 :(得分:2)

WITH q AS (
          SELECT Company.*,
                 ROW_NUMBER() OVER (PARTITION BY CompanyState, CompanyCity, CompanyName ORDER BY CompanyID) AS rnName,
                 ROW_NUMBER() OVER (PARTITION BY CompanyState, CompanyCity, CompanyAddress ORDER BY CompanyID) AS rnAddress
          FROM Company
          )
SELECT    *
WHERE     rnName > 1 OR rnAddress > 1

但请注意,如果您的数据如下所示:

CompanyID    CompanyName  CompanyAddress 
---------    -----------  --------------
1            McDonalds    Avenue 1
2            McDonalds    Avenue 2
3            Starbucks    Avenue 2

,然后将删除记录23(这是您要求的,但可能不是您想要的)

如果您只想列出所有具有重复项的行,请发出:

SELECT  *
FROM    Company co
WHERE   EXISTS
        (
        SELECT  1
        FROM    Company cn
        WHERE   cn.CompanyState = co.CompanyState
                AND cn.CompanyCity = co.CompanyCity
                AND cn.CompanyName = co.CompanyName
                AND cn.CompanyID <> co.CompanyID
        )
        OR EXISTS
        (
        SELECT  1
        FROM    Company ca
        WHERE   ca.CompanyState = co.CompanyState
                AND ca.CompanyCity = co.CompanyCity
                AND ca.CompanyAddress = co.CompanyAddress
                AND ca.CompanyID <> co.CompanyID
        )

这也适用于SQL Server 2000

(CompanyState, CompanyCity, CompanyName)(CompanyState, CompanyCity, CompanyAddress)上建立索引将大大改善此查询。

答案 1 :(得分:0)

SELECT
     C1.CompanyID,
     C2.CompanyID
FROM
     Company C1
INNER JOIN Company C2 ON
     (C2.CompanyName = C1.CompanyName OR C2.CompanyAddress = C1.CompanyAddress) AND
     C2.CompanyCity = C1.CompanyCity AND
     C2.CompanyState = C2.CompanyState AND
     C2.CompanyID > C1.CompanyID

如果您有三个或更多匹配,那么它们将在列表中多次出现。有多种方法可以处理,具体取决于您想从查询中获取什么内容。

我还强烈建议您研究更好的前端编码,以限制地址进入系统的方式以及用户培训。

答案 2 :(得分:0)

尝试这样的事情......

Select field1, field2, ... etc, count(*)
FROM Company,
GROUP BY field1, field2, ...
HAVING count(*) > 1

这应该显示重复的内容。