SQL全行重复和部分重复

时间:2017-06-27 07:07:29

标签: sql-server

我有一个表(TABLE1),包含以下字段:

MEMBERNO_PK - FIELD2_PK - FIELD3_PK - FIELD4 - FIELD5 - LOGDATETIME

前三个字段是PRIMARY KEYS。

我正在尝试从表中识别并导出三种类型的重复条目:

  1. 全行重复 - 包括LOGDATETIME字段
  2. 完整行重复项 - 不包括LOGDATETIME字段
  3. 主键重复
  4. 我不希望在我的三个导出中出现重复的行,即数字(1)中的行不应出现在export(2)中,而export(2)中的行不应出现在export(3)中。

    第1阶段

    因此,我决定使用以下SQL识别所有完整行重复项(1)并将它们插入临时表(TABLE1_FRD):

    SELECT MEMBERNO_PK,FIELD2_PK,FIELD3_PK,FIELD4,FIELD5,LOGDATETIME
    INTO TABLE1_FRD
    FROM TABLE1
    GROUP BY MEMBERNO_PK,FIELD2_PK,FIELD3_PK,FIELD4,FIELD5,LOGDATETIME
    HAVING COUNT(*)>1
    Order By MEMBNO ASC
    

    TABLE1_FRD现在包含所有完整行重复项 - 这很好。

    第2阶段

    我现在需要识别完整行重复项(不包括LOGDATETIME字段),确保从TABLE1_FRD中排除所有行。

    我能想到这样做的唯一方法是将TABLE1连接到TABLE1_FRD,然后从TABLE1_FRD中排除行 - 这在TABLE只包含几个字段时很好,但是我需要执行此操作的一些表包含一百或更多。

    有没有其他方法可以做到这一点?

    由于

1 个答案:

答案 0 :(得分:0)

这将是我的想法:
在临时表中插入带有ROW_Number列的数据。

SELECT ROW_NUMBER() OVER (PARTITION BY MemberNo_PK, Field2_PK, Field3_PK, Field4, Field5, Logdatetime  ORDER BY MemberNo_PK) ROWNUM_all
      ,ROW_NUMBER() OVER (PARTITION BY MemberNo_PK, Field2_PK, Field3_PK, Field4, Field5  ORDER BY MemberNo_PK) ROWNUM_ex_Logdatetime
      ,ROW_NUMBER() OVER (PARTITION BY MemberNo_PK, Field2_PK, Field3_PK  ORDER BY MemberNo_PK) ROWNUM_PK
      ,Table1.*
FROM Table1

现在您可以轻松地从临时表中进行选择:

完全重复:

SELECT *
  FROM yourtemptable
WHERE ROWNUM_all != 1 


除Logdatetime以外的所有列:

SELECT *
  FROM yourtemptable
WHERE (ROWNUM_all = 1 AND ROWNUM_ex_Logdatetime != 1)

刚刚PK重复:

SELECT *
  FROM yourtemptable
WHERE (ROWNUM_all = 1 AND ROWNUM_ex_Logdatetime = 1 AND ROWNUM_PK != 1)

如果您不希望将数据存储在temp.table中以供进一步使用,那么您也可以在一个选择中处理所有内容。
在一个选择中处理这个将是:

SELECT   CASE WHEN (a.ROWNUM_all != 1)
              THEN  'FULL duplicate'
              WHEN (ROWNUM_all = 1 AND ROWNUM_ex_Logdatetime != 1)
              THEN 'Duplicate all columns except Logdatetime' 
              WHEN (ROWNUM_all = 1 AND ROWNUM_ex_Logdatetime = 1 AND ROWNUM_PK != 1)
              THEN 'just PK-duplicate'
         END as info
        ,a.MemberNo_PK
        ,a.Field2_PK 
        ,a.Field3_PK 
        ,a.Field4 
        ,a.Field5 
        ,a.Logdatetime
FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY MemberNo_PK, Field2_PK, Field3_PK, Field4, Field5, Logdatetime  ORDER BY MemberNo_PK) ROWNUM_all
      ,ROW_NUMBER() OVER (PARTITION BY MemberNo_PK, Field2_PK, Field3_PK, Field4, Field5  ORDER BY MemberNo_PK) ROWNUM_ex_Logdatetime
      ,ROW_NUMBER() OVER (PARTITION BY MemberNo_PK, Field2_PK, Field3_PK  ORDER BY MemberNo_PK) ROWNUM_PK
      ,Table1.*
FROM Table1
) a
WHERE ROWNUM_all != 1 
   OR ROWNUM_ex_Logdatetime != 1 
   OR ROWNUM_PK != 1

我用一些testdata创建了一个rextester,所以每个人都可以重现它。这是链接:http://rextester.com/AVJ95318