Tsql SQL Server 2008重复数据消除

Tsql SQL Server 2008重复数据消除,tsql,sql-server-2008,deduplication,Tsql,Sql Server 2008,Deduplication,长话短说,我接管了一个项目,数据库中的一个表非常需要重复数据消除。该表如下所示: supply_req_id | int | [primary key] supply_req_dt | datetime | request_id | int | [foreign key] supply_id | int | [foreign key] is_disabled | bit | DELETE FROM [table] WHERE supp

长话短说,我接管了一个项目,数据库中的一个表非常需要重复数据消除。该表如下所示:

supply_req_id | int      | [primary key]
supply_req_dt | datetime | 
request_id    | int      | [foreign key]
supply_id     | int      | [foreign key]
is_disabled   | bit      |
DELETE FROM [table] WHERE supply_req_id NOT IN
(SELECT supply_req_id from [table] t 
INNER JOIN
    (SELECT MAX(supply_req_dt) dt, request_id, supply_id 
    FROM [table] 
    GROUP BY request_id, supply_id) d
ON t.supply_req_dt = d.dt
AND t.request_id = d.request_id 
AND t.supply_id = d.supply_id)
重复存在于具有相同请求id和提供id的记录中。我想找到消除此表重复的最佳实践方法

[编辑]
@柯克·布罗德赫斯特,谢谢你的提问。由于supply_req_id没有在其他任何地方引用,因此我的回答是保留第一个,删除任何后续事件


“快乐假日”

似乎应该有一个用于此的命令,但可能是因为我习惯了另一个数据库服务器。以下是相关的支持文档:

如何在SQL Server中从表中删除重复行

似乎应该有一个用于此的命令,但可能是因为我习惯了另一个数据库服务器。以下是相关的支持文档:

如何在SQL Server中从表中删除重复行

您需要澄清您的规则,以确定在“匹配”情况下要保留的记录-最新的、最早的、禁用了
的记录是正确的还是错误的

一旦确定了该规则,剩下的就相当简单了:

  • 选择要保留的记录-不同的
    记录
  • 连接回原始表以获取这些记录的ID
  • 删除所有不在联接数据集中的内容
  • 假设您想保留任何“重复”对的最新记录。您的查询如下所示:

    supply_req_id | int      | [primary key]
    supply_req_dt | datetime | 
    request_id    | int      | [foreign key]
    supply_id     | int      | [foreign key]
    is_disabled   | bit      |
    
    DELETE FROM [table] WHERE supply_req_id NOT IN
    (SELECT supply_req_id from [table] t 
    INNER JOIN
        (SELECT MAX(supply_req_dt) dt, request_id, supply_id 
        FROM [table] 
        GROUP BY request_id, supply_id) d
    ON t.supply_req_dt = d.dt
    AND t.request_id = d.request_id 
    AND t.supply_id = d.supply_id)
    
    问题是,如果
    supply_req_dt
    也被复制,那么您将保留这两个副本。修复方法是执行另一个
    groupby
    ,然后选择顶部的
    id

    select MAX(supply_req_id), supply_req_dt, request_id, supply_id 
    group by supply_req_dt, request_id, supply_id 
    

    作为过渡步骤。但是如果你不需要这样做,就不用费心了。

    你需要澄清你的规则,以确定在“匹配”的情况下保留哪一条记录——最近的、最早的、禁用了
    的记录是正确的还是错误的

    一旦确定了该规则,剩下的就相当简单了:

  • 选择要保留的记录-不同的
    记录
  • 连接回原始表以获取这些记录的ID
  • 删除所有不在联接数据集中的内容
  • 假设您想保留任何“重复”对的最新记录。您的查询如下所示:

    supply_req_id | int      | [primary key]
    supply_req_dt | datetime | 
    request_id    | int      | [foreign key]
    supply_id     | int      | [foreign key]
    is_disabled   | bit      |
    
    DELETE FROM [table] WHERE supply_req_id NOT IN
    (SELECT supply_req_id from [table] t 
    INNER JOIN
        (SELECT MAX(supply_req_dt) dt, request_id, supply_id 
        FROM [table] 
        GROUP BY request_id, supply_id) d
    ON t.supply_req_dt = d.dt
    AND t.request_id = d.request_id 
    AND t.supply_id = d.supply_id)
    
    问题是,如果
    supply_req_dt
    也被复制,那么您将保留这两个副本。修复方法是执行另一个
    groupby
    ,然后选择顶部的
    id

    select MAX(supply_req_id), supply_req_dt, request_id, supply_id 
    group by supply_req_dt, request_id, supply_id 
    

    作为过渡步骤。但是,如果您不需要这样做,就不用麻烦了。

    这将为(supply\u req\u dt,request\u id)分组中的每一行创建一个列组,从1=最低supply\u req\u id开始。任何dupe的值都大于1

    ;WITH cDupes AS
    (
        SELECT
         supply_req_id,
         ROW_NUMBER() OVER (PARTITION BY supply_req_dt, request_id ORDER BY supply_req_id) AS RowNum
        FROM
         MyTable
    )
    DELETE
       cDupes
    WHERE
       RowNum > 1
    
    然后添加唯一的约束或索引

    CREATE UNIQUE INDEX IXU_NoDupes ON MyTable (supply_req_dt, request_id)
    

    这将为(supply_req_dt,request_id)分组中的每一行创建一个列组,从1=最低supply_req_id开始。任何dupe的值都大于1

    ;WITH cDupes AS
    (
        SELECT
         supply_req_id,
         ROW_NUMBER() OVER (PARTITION BY supply_req_dt, request_id ORDER BY supply_req_id) AS RowNum
        FROM
         MyTable
    )
    DELETE
       cDupes
    WHERE
       RowNum > 1
    
    然后添加唯一的约束或索引

    CREATE UNIQUE INDEX IXU_NoDupes ON MyTable (supply_req_dt, request_id)
    

    当您发现一个副本时,您将如何决定“保留”哪一个和删除哪一个?当您发现一个副本时,您将如何决定“保留”哪一个和删除哪一个?