基于匹配列数的SQL重复数据删除

时间:2014-10-22 06:24:58

标签: sql tsql

我正在尝试根据记录之间的匹配列数找到有关如何重复数据删除表的信息。

假设我的数据源看起来像

---------------------------------------------------
| ColumnA | ColumnB | ColumnC | ColumnD | ColumnN |
---------------------------------------------------
| Peter   | Dink    | Midget  | NULL    | 0738455 |
| Peter   | Dink    | Child   | 334AA   | 49595   |
| Mark    | Walhg   | Funky   | 334AA   | 0738455 | 
| Mark    | Dink    | NULL    | NULL    | NULL    |
| Mark    | Walhg   | Funky   | 334AA   | NULL    |
| Peter   | Dink    | NULL    | NULL    | 0738455 |
---------------------------------------------------

基本上我希望能够提供共享2,3,4等数据列的记录数;但是我需要将此约束仅限于列的选择子集(并忽略NULL /空格)。

根据上面的数据,我希望能够说:

  1. 有5列匹配的0条记录
  2. 有4列(3,5)
  3. 匹配1条记录
  4. 有3列(1,6)(3,5)
  5. 匹配1条记录
  6. 在2列(1,6)(2,6)(3,5)(1,2)
  7. 上有2条记录匹配

    随着匹配列的数量变得越来越少,我还需要它“降低”。所以在上面我的数据在检查5列的匹配后是相同的。然后在4列上将数据简化为:

    ---------------------------------------------------
    | ColumnA | ColumnB | ColumnC | ColumnD | ColumnN |
    ---------------------------------------------------
    | Peter   | Dink    | Midget  | NULL    | 0738455 |
    | Peter   | Dink    | Child   | 334AA   | 49595   |
    | Mark    | Walhg   | Funky   | 334AA   | 0738455 | 
    | Mark    | Dink    | NULL    | NULL    | NULL    |
    | Peter   | Dink    | NULL    | NULL    | 0738455 |
    ---------------------------------------------------
    

    第5栏已经消失,因为它已被删除(我不知道我是如何决定删除哪一个,可能是在某个日期专栏)。所以我可以说删除了1条记录。

    检查3列后:

    ---------------------------------------------------
    | ColumnA | ColumnB | ColumnC | ColumnD | ColumnN |
    ---------------------------------------------------
    | Peter   | Dink    | Midget  | NULL    | 0738455 |
    | Peter   | Dink    | Child   | 334AA   | 49595   |
    | Mark    | Walhg   | Funky   | 334AA   | 0738455 | 
    | Mark    | Dink    | NULL    | NULL    | NULL    |
    ---------------------------------------------------
    

    所以我可以说另一个被删除了。

    然后是两列:

    ---------------------------------------------------
    | ColumnA | ColumnB | ColumnC | ColumnD | ColumnN |
    ---------------------------------------------------
    | Peter   | Dink    | Midget  | NULL    | 0738455 |
    | Mark    | Walhg   | Funky   | 334AA   | 0738455 | 
    | Mark    | Dink    | NULL    | NULL    | NULL    |
    ---------------------------------------------------
    

    删除了另一列。

    我认为我接近它的方式是给出一个权重,该权重基本上是来自所选列的匹配数据点的数量。例如,也许我不想使用Country列计为匹配列之一,我只会使用标识记录的内容,如姓名和电话号码。

    然后我可以看看每个权重(列匹配的数量)扣除了多少记录,并决定我们将使用7个匹配的身份数据列重复删除所有内容;并在一条记录中汇总任何值为NULL /空白的重复记录。

    这一切都超出了我的范围。我知道我想做什么;只是不知道该怎么做。

1 个答案:

答案 0 :(得分:1)

我希望我理解正确。这是我对如何做到这一点的想法,它不完整你可以使用动态sql和while循环自动化它以通过所有id并在以后统一结果。

IF OBJECT_ID('TestTable1') IS NOT NULL 
DROP TABLE TestTable1

CREATE TABLE TestTable1 (
    ID INT IDENTITY(1,1),
    ColumnA NVARCHAR(100),
    ColumnB NVARCHAR(100),
    ColumnC NVARCHAR(100),
    ColumnD NVARCHAR(100),
    ColumnE INT
)

INSERT INTO TestTable1 VALUES 
('Peter','Dink','Milk',NULL,0738455),
('Peter','Dink','Beer','334AA',49595),
('Mark','Walk','Funky','334AA',0738455),
('Mark','Dink',NULL,NULL,NULL),
('Mark','Walk','Funky','334AA',NULL),
('Peter','Dink',NULL,NULL,0738455)

DECLARE @ID INT
SET @ID = 1

SELECT * FROM TestTable1 WHERE ID IN 
(
    SELECT ID FROM
    (   
        SELECT @ID AS ID
        UNION
        SELECT b.ID FROM TestTable1 as a
        CROSS APPLY TestTable1 as b
        WHERE a.ColumnA = b.ColumnA
        AND a.ID = @ID AND b.ID <> @ID
    ) AS OneMatchingColumn
) 


SELECT * FROM TestTable1 WHERE ID IN 
(
    SELECT ID FROM
    (
        SELECT @ID AS ID
        UNION
        SELECT b.ID FROM TestTable1 as a
        CROSS APPLY TestTable1 as b
        WHERE a.ColumnA = b.ColumnA
        AND a.ColumnB = b.ColumnB
        AND a.ID = @ID AND b.ID <> @ID
    ) AS TwoMatchingColumns
)


SELECT * FROM TestTable1 WHERE ID IN 
(
    SELECT ID FROM
    (
        SELECT @ID AS ID
        UNION
        SELECT b.ID FROM TestTable1 as a
        CROSS APPLY TestTable1 as b
        WHERE a.ColumnA = b.ColumnA
        AND a.ColumnB = b.ColumnB
        AND a.ColumnC = b.ColumnC
        AND a.ID = @ID AND b.ID <> @ID
    ) AS ThreeMatchingColumns
)