在具有来自另一个表的附加数据集的行中搜索重复项

时间:2012-12-13 16:19:52

标签: sql tsql duplicate-removal

我需要从表中删除重复记录。语法:T-SQL(MS SQL Server)

它有两个困难:

  1. 有些字段包含不应影响行比较的数据
  2. 还有一个与第一个关联的表与“一对多”关系
  3. 示例:

    Table A                 Table B
    --------------          --------------
    AId - int       <-\     BId - int
    A1 - int           \->  AId - int
    A2 - varchar            B6 - varchar
    A3 - varchar            B7 - varchar
    A4 - varchar            B8 - varchar
    A5 - int                B9 - int
    

    因此,表A中的任何记录都包含字段AId,A1,A2,A3,A4和A5,以及“子记录”列表:表B中记录的列表,其中B.AId与A.AId匹配。例如,它可以是采购交易清单,其中表A包含交易属性,例如日期/时间或客户ID,表B可以表示货物清单及其价格和金额。

    一旦某些记录重复出现。它们具有不同的AId,不同的BId,不同的A4,A5,B8和B9。所有其他字段应匹配,以使两个记录重复。

    因此,如果出现以下情况,A中的两个记录X和Y将被视为重复:

    • X.A1 == Y.A1
    • X.A2 == Y.A2
    • 表B中所有带有AId == X.AId的记录完全匹配B中所有AID == Y.AId的记录,但不包括(忽略)B8和B9字段

    我至少需要获得这些重复记录的AID,最多删除那些重复记录,但只留下一份记录副本(无论哪一个)。

    请告诉我是否需要以下说明。提前谢谢。

    upd: SQL小提琴:http://sqlfiddle.com/#!3/898c8/1

2 个答案:

答案 0 :(得分:0)

Select a1, Count(CompareField) From (Select a.a1 as a1, a.a1 + a.a2 +  a.a3 + b.b6 + b.b7 as compareField from A inner join b on a.AID = b.AID) z Group by z.comparefield

这将为您提供所有重复项的列表,然后您可以使用外部查询删除记录从(prevquery)中的Where AID中删除

可能不需要说明但是,请确保在运行您的DELETE QUERY之前备份数据库。 :)

答案 1 :(得分:0)

诀窍是将表B中的多行连接到单个字符串。

对于SQL Server,您可以滥用XML功能(如果值中有特殊字符,则可能会出现问题 - 其他人在Sybase中有内置函数,如LIST(),它返回以逗号分隔的列表):

SELECT AID, A1, A2, A3, (
  SELECT B6, B7
  FROM B
  WHERE AID=A.AID
  ORDER BY B6, B7
  FOR XML RAW
) XML
FROM A

http://sqlfiddle.com/#!3/898c8/29/0

现在你有一个平面表,很容易找到和删除重复项(这是留给读者的练习)......