Sql 通过删除重复项将一个关系修复为一个多关系

Sql 通过删除重复项将一个关系修复为一个多关系,sql,sql-server,duplicates,Sql,Sql Server,Duplicates,错误 最初,组织和服务器之间存在一对一的关系,其中服务器的密钥只是一个OrganizationId,这是一个非常糟糕的设计,因为业务逻辑发生了变化,现在多个组织可以拥有同一台服务器。在进行更改之前,我们只是为每个组织复制了服务器,因此多个组织将拥有具有相同子域的服务器。下面是当前的设置 要求 首先,不幸的是,这是一个有大量数据的prod,因此使用正确的模型删除整个数据库有点不可能 我们现在要做的是删除不同子域上的重复服务器,例如,如果Org1和Org2都有带有子域“test”的Ser1和Ser

错误

最初,组织和服务器之间存在一对一的关系,其中服务器的密钥只是一个OrganizationId,这是一个非常糟糕的设计,因为业务逻辑发生了变化,现在多个组织可以拥有同一台服务器。在进行更改之前,我们只是为每个组织复制了服务器,因此多个组织将拥有具有相同子域的服务器。下面是当前的设置

要求

首先,不幸的是,这是一个有大量数据的prod,因此使用正确的模型删除整个数据库有点不可能

我们现在要做的是删除不同子域上的重复服务器,例如,如果Org1和Org2都有带有子域“test”的Ser1和Ser2,我们将使FK Org.Server_Id成为具有该域的服务器(在本例中为Ser1)的最低发生率,因此对于Org1和Org2,它们的服务器都将是Ser1。下面是一个高科技excel示例:

我们尝试过的事情

根据Server.OrganizationId,我们可以通过以下方式将Org.Server_Id设置为正确的值:

UPDATE Organization 
SET Server_Id = t.Id
FROM(
    SELECT Id, OrganizationId
    FROM Server
) t
WHERE t.OrganizationId = Organization.Id
但是,每当我们尝试更进一步时,我们就会陷入困境,因为我们无法使用内部FROM中的orderby来尝试以某种聚合方式抓住第一个事件

这就是我们最终要做的,但它当然不起作用,因为我们无法从内部访问t,我也不认为这是正确的路径:

UPDATE Organization SET Server_Id = t.Id  
FROM  
(  
    SELECT Id, OrganizationId
    FROM (
        SELECT TOP(1) Subdomain, Id, OrganizationId
        FROM Server
        WHERE Subdomain = t.Subdomain
    ) a
) t  
WHERE t.OrganizationId = Organization.Id

我不能说我完全理解您正在进行的一切,但是在过去,当我需要获取第一条重复信息时,我在内部查询中使用了一个分区函数。我不知道您希望如何排序结果,但它看起来是这样的:

 (
 SELECT ROW_NUMBER() OVER (PARTITION BY column1, column2, etc... ORDER BY columnX DESC/ASC) As row_num, Id, OrganizationId
 FROM Server
 ) t
 WHERE t.OrganizationId = Organization.Id AND row_num = 1

这与您在第二个代码块中尝试执行的操作基本相同(我相信)。column1和column2是要折叠为一个条目的重复数据列的集合,columnX是按其排序结果的列。通过在WHERE语句中使用row_num=1,您将只返回每个唯一列1、列2等的第一个结果。。来自内部查询的组合。

使用@user2731076建议的分区后,我们可以将查询修改为:

UPDATE Organization SET Server_Id = t.Id  
FROM  
(
    SELECT ROW_NUMBER() OVER (PARTITION BY Subdomain ORDER BY [Server].Id ASC) As row_num, [Server].Id, OrganizationId, Subdomain
    FROM Organization
    INNER JOIN [Server] ON [Server].OrganizationId = [Organization].Id
) t
WHERE t.Subdomain IN(SELECT Subdomain FROM Server WHERE OrganizationId = Organization.Id) AND row_num = 1
我们的代码存在以下问题:

t.OrganizationId = Organization.Id
因为总是有一个服务器与一个组织相关联,所以它只会将Org.Server_Id的值设置为它已经设置的值。因此,我们想要找到的第一个实例是服务器的行_num=1,它的子域与当前组织服务器的子域相似。这需要内部连接从分区抓取它,并通过WHERE子句中的IN语句从当前组织抓取它,因此我们可以为我们的组织执行t.Subdomain=Subdomain

也许有一种更有效的方法可以做到这一点,我们将在未来对此进行研究