使用T SQL列出重复记录

使用T SQL列出重复记录,sql,sql-server,database,sql-server-2008,Sql,Sql Server,Database,Sql Server 2008,我有一个数据库,用于记录一家小型诊所的患者信息。我们使用MS SQL Server 2008作为后端。“患者”表包含以下列: Id int identity(1,1), FamilyName varchar(30), FirstName varchar (20), DOB datetime, AddressLine1 varchar (50), AddressLine2 varchar (50), State varchar (20), Postcode varchar (4),

我有一个数据库,用于记录一家小型诊所的患者信息。我们使用MS SQL Server 2008作为后端。“患者”表包含以下列:

Id int identity(1,1), 
FamilyName varchar(30),
FirstName varchar (20), 
DOB datetime, 
AddressLine1 varchar (50), 
AddressLine2 varchar (50), 
State varchar (20), 
Postcode varchar (4), 
NextOfKin varchar (20), 
Homephone varchar (20), 
Mobile varchar (20)
有时,工作人员会登记新患者,但不知道该患者在系统中已有记录。我们最终得到了数千条重复记录

我想做的是提供一份有重复记录的患者名单,以便工作人员在安静时间合并。我们认为,如果2个记录具有完全相同的家族名称、第一名称和DOB,那么2个记录将被复制。我现在正在做的是使用子查询返回记录,如下所示:

SELECT FamilyName, 
       FirstName, 
       DOB, 
       AddressLine1, 
       AddressLine2, 
       State, 
       Postcode, 
       NextOfKin, 
       HomePhone,
       Mobile 
FROM
Patients AS p1 
WHERE Id IN 
          ( 
            SELECT Max(Id) 
            FROM Patients AS p2, 
            COUNT(id) AS NumberOfDuplicate 
            GROUP BY    
            FamilyName, 
            FirstName, 
            DOB HAVING COUNT(Id) > 1
          )

这会产生结果,但性能很差。有没有更好的办法?唯一的要求是我需要显示Patients表中的所有字段,因为系统的用户希望在决定是否合并记录之前查看所有详细信息

我建议您在用于检测重复项的3个字段上建立索引, 然后尝试以下查询:

with Duplicates as
( 
    select FamilyName, FirstName, DOB
    from Patients 
    group by FamilyName, FirstName, DOB
    having count(*) > 1 
)
Select Patients.* 
from Patients 
    inner join Duplicates
    on Patients.FamilyName = Duplicates.FamilyName 
       And Patients.FirstName= Duplicates.FirstName
       and Patients.DOB= Duplicates.DOB

如果我处在你的位置,我会做以下事情:

  • 为FamilyName、FirstName和DOB添加索引
  • 为子查询创建视图
  • 修改查询如下

    从患者p内部连接视图中选择p.\u name v ON v.FirstName=p.FirstName和…


  • 这将根据firstname和lastname输出每一个具有重复项的行

    SELECT DISTINCT t1.* 
    FROM Table AS t1 
        INNER JOIN Table AS t2
        ON t1.firstname = t2.firstname 
           AND t1.lastname = t2.lastname
           AND t1.id <> t2.id
    
    选择不同的t1。*
    从表中选择t1
    内部联接表作为t2
    在t1.firstname=t2.firstname上
    和t1.lastname=t2.lastname
    和t1.id t2.id
    
    将显示所有副本


    但是,请考虑名字写的不同,但相似。您可能需要查找主题“重复数据消除”和/或“记录链接”。我使用字符串相似性算法(修改的Jaro/Winkler和levenshtein)解决了这个问题。

    这将列出每个重复项的所有行。我已经有了这3个字段的综合索引。明天我回来工作时,我会按照你的建议试试CTE。只是想知道另一种方法是否可读性更好,这是否意味着CTE在性能方面优于子查询?谢谢,您的解决方案可以工作,但我最终使用了Join方法,因为不知为什么CTE比Join稍微慢一点。感谢您的帮助。这实际上是我计划做的下一步,因为预构建的SQL视图将有一些统计数据源,可以提高性能。哇,这是一个优雅的解决方案。我从来没有想过这样做,谢谢我最终使用了您的解决方案,而不是CTE解决方案,因为join语句似乎提供了更好的性能。请问我如何接受你的解决方案?这样更好吗?不是说不是,但你应该解释一下。@itsburse对于start-OP查询将抛出错误,其次,你的问题涉及很多方面,所以简单地说哪个更好是不正确的,然而,人们可以比较他们的执行计划。但是,如果你能对这件事有所了解,请做。@itsburse然而,我想知道你的评论,我的查询如何更好?顺便说一句,谢谢你提出了一个好问题。
    WITH CTE 
    AS
    (
    SELECT Id, FamilyName, FirstName ,DOB
    ROW_NUMBER() OVER(PARTITION BY FamilyName, FirstName ,DOB ORDER BY Id) AS DuplicateCount
    FROM PatientTable
    )
    select * from CTE where DuplicateCount > 1
    
     select FamilyName, FirstName, DOB 
       from Patients 
      group by FamilyName, FirstName, DOB 
     having count(*)>1