仅更新第一个匹配的记录而不重复记录

时间:2017-11-27 11:21:35

标签: sql sql-server-2012

我在表A(名字,姓氏,标签)中有记录,而且标签列是空的,这列上的记录将复制相同的名字和姓氏

Table A
{     
first name =’Mohamed’, Last name =’Ahmed’, Tag=’’,
first name =’Mohamed’, Last name =’Ahmed’, Tag=’’,
first name =’Mohamed’, Last name =’Ahmed’, Tag=’’,
first name =’Ibrahim’, Last name =’Ahmed’, Tag=’’
}

我有另一个表A,列完全相同,记录多于表A,所有记录都有标签,记录也可以重复。

Table B
{ 
first name =’Mostafa’, Last name =’hamza’, Tag=’3245435’,
first name =’Ayman’, Last name =’Malek’, Tag=’45455’,
first name =’Mohamed’, Last name =’Ahmed’, Tag=’12345’,
first name =’Mohamed’, Last name =’Ahmed’, Tag=’87654’,
first name =’Ibrahim’, Last name =’Ahmed’, Tag=’658568’
}

我想更新表A上的标签,具体取决于表B上的相应值。只有我可以在表A上找到唯一标签。

问题是当我尝试使用update语句更新并且表B上的最后一个标记与条件匹配时,总是更新表A中的整个匹配记录,因此映射不正确,如下所示:

  Table A
    { 
    first name =’Mohamed’, Last name =’Ahmed’, Tag=’87654’,
    first name =’Mohamed’, Last name =’Ahmed’, Tag=’87654’,
    first name =’Ibrahim’, Last name =’Ahmed’, Tag=’658568’
    }

,所需的输出应为:

  Table A
    { 
    first name =’Mohamed’, Last name =’Ahmed’, Tag=’12345’,
    first name =’Mohamed’, Last name =’Ahmed’, Tag=’87654’,
    first name =’Mohamed’, Last name =’Ahmed’, Tag=’’,
    first name =’Ibrahim’, Last name =’Ahmed’, Tag=’658568’
    }

1 个答案:

答案 0 :(得分:0)

您可以为CTE中的两个表分配行号,然后执行更新连接:

WITH cteA AS (
    SELECT [first name], [Last name], Tag,
        ROW_NUMBER() OVER (PARTITION BY [first name], [Last name] ORDER BY Tag) rn
    FROM tableA
),
cteB AS (
    SELECT [first name], [Last name], Tag,
        ROW_NUMBER() OVER (PARTITION BY [first name], [Last name] ORDER BY Tag) rn
    FROM tableA
)

UPDATE a
SET Tag = b.Tag
FROM cteA a
INNER JOIN cteB b
    ON a.[first name] = b.[first name] AND
       a.[Last name] = b.[Last name] AND
       a.rn = b.rn;

这里的技巧是为名字/姓氏组中的每个记录分配一个行号。对于表A,行号的赋值没有意义,因为没有标记,但在您的示例中,两个记录中的一个将被分配1而另一个2.对于表B,行号的分配将取决于订购标签。同样,这种排序可能无关紧要,但结合这两个行号为我们提供了一种方法,可以确保表B中的每条记录仅逻辑映射到表A中的单个记录。