2011-12-08 58 views
3

我需要创建一个递归UPDATE语句从另一个表,以便为前..递归更新语句

Table1 
    (
     IdNumberGeneratedFromAService INT NOT NULL, 
     CodeName NVARCHAR(MAX) 
    ) 

    Table2 
    (
     Table2Id Auto_Increment, 
     Name NVARCHAR(MAX), 
     IdNumberThatComesFromTabl1, 
     CodeNameForTable1ToMatch 
    ) 

的问题是CodeNameForTable1ToMatch更新不是唯一的,所以如果目录一有2个为IDNumber中相同的代码,有Table2中有两行,CodeName相同我想更新Table2中的行,以便第一行获取第一个idnumber,第二行获取第二个id号。

也想这样做,而不光标....

SAMPLE DATA 

Table1 
idNumber   Code 
C145-6678-90  Code1 
C145-6678-91  Code1 
C145-6678-92  Code1 
C145-6678-93  Code1 
C145-6678-94  Code1 


Table 2 
AutoIncrementIdNumber  Code  IdNumber 
1    Code1  {NULL} 
2    Code1  {NULL} 
3    Code1  {NULL} 
4    Code1  {NULL} 
5    Code1  {NULL} 


C145-6678-90 needs to got 1 
C145-6678-91 needs to got 2 
C145-6678-92 needs to got 3 
C145-6678-93 needs to got 4 
C145-6678-94 needs to got 5 

in one update statement 
+4

你能为此提供一些样本数据吗? –

+1

你能为我们覆盖所有的角落案例吗?如果Table有3个代码的ID,但该代码在Table2中只出现两次?对于特定的代码,Table2有可能比Table1有更多的行吗? – MatBailie

+0

您是否可以修改您的示例数据,以便Table2有额外的行并告诉我们该案例的预期结果? –

回答

-3

这也不是没有可能的光标。

+4

我不会跳到这个结论。如果Table1和Table2始终具有相同的CodeName出现次数,则可以使用RowNumber()创建并添加其他字段,以确保1:1关系。但OP需要更清楚地表达数据的确切行为,以及他需要的确切逻辑取决于数据。 – MatBailie

+0

表1和表2没有相同的编号 – dpak

+3

我相信这将是可能的,没有游标。无论如何,使用游标的TBH实际上并不会让事情变得更容易。 @ user589510 - 你为什么如此迅速地接受了这个断言?你甚至还没有完全澄清你的要求,这将允许人们提交非游标解决方案。 –

6

在由代码分区的每个表上使用ROW_NUMBER窗口函数,可以对每个具有共同代码的行进行编号,然后组合每个查询的结果以匹配基于代码的行以及该代码的编号实例。因此,在表1将第一代码A表2匹配的第一个代码A,等

示例代码显示这(SQL 2005或更高版本):

-- Sample code prep 
CREATE TABLE #Table1 
(
    IdNumberGeneratedFromAService INT NOT NULL, 
    CodeName NVARCHAR(MAX) 
); 

CREATE TABLE #Table2 
(
    Table2Id INT NOT NULL IDENTITY(1,1), 
    Name NVARCHAR(MAX), 
    IdNumberThatComesFromTabl1 INT NULL, 
    CodeNameForTable1ToMatch NVARCHAR(MAX) 
); 


INSERT INTO #Table1(IdNumberGeneratedFromAService, CodeName) 
VALUES(100,'Code A'),(150,'Code A'),(200,'Code B'),(250,'Code A'),(300,'Code C'),(400,'Nonexistent'); 

INSERT INTO #Table2(Name, IdNumberThatComesFromTabl1, CodeNameForTable1ToMatch) 
VALUES('A1-100',0,'Code A'),('A2-150',0,'Code A'),('A3-250',0,'Code A'),('B1-200',0,'Code B'),('C1-300',0,'Code C'),('No Id For Me',0,'Code No Id :('); 

-- Sample select statement that shows the row numbers 
--SELECT * 
--FROM 
-- (SELECT *, ROW_NUMBER() OVER (Partition By IT2.CodeNameForTable1ToMatch Order By IT2.Table2Id) as RowNum 
--  FROM #Table2 IT2) T2 
-- INNER JOIN 
-- (SELECT *, ROW_NUMBER() OVER (Partition By IT1.CodeName Order By IT1.IdNumberGeneratedFromAService) as RowNum 
--  FROM #Table1 IT1) T1 
--  ON T1.CodeName = T2.CodeNameForTable1ToMatch AND T1.RowNum = T2.RowNum; 

-- Table 2 Before 
SELECT * FROM #Table2; 

-- Actual update statement 
UPDATE #Table2 
SET IdNumberThatComesFromTabl1 = T1.IdNumberGeneratedFromAService 
FROM #Table2 AT2 
INNER JOIN 
    (SELECT *, ROW_NUMBER() OVER (Partition By IT2.CodeNameForTable1ToMatch Order By IT2.IdNumberThatComesFromTabl1) as RowNum 
     FROM #Table2 IT2) T2 
    ON T2.Table2Id = AT2.Table2Id 
INNER JOIN 
    (SELECT *, ROW_NUMBER() OVER (Partition By IT1.CodeName Order By IT1.IdNumberGeneratedFromAService) as RowNum 
     FROM #Table1 IT1) T1 
     ON T1.CodeName = T2.CodeNameForTable1ToMatch AND T1.RowNum = T2.RowNum; 

-- Table 2 after 
SELECT * FROM #Table2; 

-- Cleanup 
DROP TABLE #Table1; 
DROP TABLE #Table2; 

我把你的两个示例表到临时表格,并添加了'代码A'的3条记录,'代码B'的记录以及'代码C'的记录。表1中的代码根据表1 ID的顺序进行编号,表2中的代码通过自动递增的表2 ID进行排序。我还在每张表格中加入了一张不会与另一张相匹配的记录。我试图让代码的描述性更容易看到发生了正确的匹配(他们为了表2的顺序很重要,因为它有一个自动递增的ID)

注释掉的示例选择有助于理解在我将它加入到UPDATE语句之前,选择是如何工作的。

所以我们可以在更新之前看到表2全部为0,然后我们更新表2中的值,其中唯一表2的id与我们编号匹配的匹配连接中的唯一表2的id匹配,然后我们从表中选择2再次查看结果。

+1

对不起,我在此张贴延误抱歉,显然是不可能的需要稍长:) – Tarwn

+0

我站好了,很好的回答。我不得不说,我从来没有处理过更多的琐事,那么我在与开发人员打交道时会这么做:)我不认为这是可能的,因此我给出了我的答案。干杯! – Craig

+1

我的意思是说真诚的评论,我在这个游戏中的时间越长,我越想避免这个词不可能,因为每次我使用它时都会有人不可避免地证明我错了:) – Tarwn

1

上Tarwn的解决方案一个RIFF:

with cte1 as (
    select code, row_number() over (partition by code order by idNumber) as [rn] 
    from table1 
), cte2 as (
    select code, row_number() over (partition by code order by AutoIncrementIdNumber) as [rn] 
    from table2 
) 
update cte2 
set idNumber = cte1.idNumber 
from cte2 
inner join cte1 
    on cte2.code = cte1.code 
    and cte2.rn = cte1.rn 

我只是提出这个,因为人们常常惊讶,你可以更新公用表表达式。