SQL更新目标表中具有相同ID但来自源表的不同值的多行

use*_*358 4 sql-server sql-server-2008-r2 update

我有两个不同的表,其中有一个名为 id 的公共列:

Table1
----  -------
id  |  Date
----  -------
1      null
1      null
2      null
2      null
2      null
2      null
3      null
4      null
4      null

Table2
----  -------
id  |  Date
----  -------
1      2013-01-29 08:50:00.000
1      2013-01-29 15:28:00.000
2      2013-01-31 11:56:00.000
2      2013-03-11 16:08:00.000
2      2013-01-31 14:04:00.000
2      2013-01-31 14:08:00.000
3      2013-02-28 23:44:00.000
4      2013-01-31 14:04:00.000
4      2013-01-31 14:08:00.000
Run Code Online (Sandbox Code Playgroud)

我需要写一个更新语句,将主要从把值的第一行与ID = 1Table2Table1一个id = 1,第二行与ID = 1,从Table2进入Table1一个id = 1,这样Table1现在看起来是这样

Table1
----  -------
id  |  Date
----  -------
1      2013-01-29 08:50:00.000
1      2013-01-29 15:28:00.000
Run Code Online (Sandbox Code Playgroud)

目前这个SQL语句

UPDATE Table1
  SET Table1.date = T2.date
  FROM 
  Table2 T2
  INNER JOIN Table1 T1
  ON T1.date = T2.date
Run Code Online (Sandbox Code Playgroud)

正在Table1这个样子的,它适用于发现该ID的第一次约会到所有匹配的IDS行的目标表

Table2
----  -------
id  |  Date
----  -------
1      2013-01-29 08:50:00.000
1      2013-01-29 08:50:00.000
Run Code Online (Sandbox Code Playgroud)

有没有办法让 udpateTable1看起来像下面这样:

Table1
----  -------
id  |  Date
----  -------
1      2013-01-29 08:50:00.000
1      2013-01-29 15:28:00.000
2      2013-01-31 11:56:00.000
2      2013-03-11 16:08:00.000
2      2013-01-31 14:04:00.000
2      2013-01-31 14:08:00.000
3      2013-02-28 23:44:00.000
4      2013-01-31 14:04:00.000
4      2013-01-31 14:08:00.000
Run Code Online (Sandbox Code Playgroud)

有没有办法在 SQL 语句中做到这一点?我不想最好使用游标。

两个表中都有其他列,并不是所有的id值都Table1可能存在,Table2反之亦然。我不想触及或改变的那些其他行和列。

mar*_*uso 8

找不到 SQL Server 2008 小提琴引擎,所以我不得不选择 SQL Server 2014 ......所以不确定以下是否适用于 SQL Server 2008,但 fwiw ...

设置一些示例数据:

create table Table1(id int, Date datetime null);
create table Table2(id int, Date datetime);

insert Table1 values (1,null)
insert Table1 values (1,null)
insert Table1 values (2,null)
insert Table1 values (2,null)
insert Table1 values (2,null);

insert Table2 values (1,'2013-01-29 08:50:00.000')
insert Table2 values (1,'2013-01-29 15:28:00.000')
insert Table2 values (2,'2013-01-31 11:56:00.000')
insert Table2 values (2,'2013-03-11 16:08:00.000')
insert Table2 values (2,'2013-01-31 14:04:00.000');
Run Code Online (Sandbox Code Playgroud)

请记住,我们还没有提供任何方法来确定给定 id 值在 Table1 和 Table2 之间匹配哪些行,我只会让 row_number() 生成一个“匹配”的 rowid。

然后我们将利用 SQL Server 通过派生表定义更新 Table1 的能力:

update T1 
set    T1.Date=T2.Date

from   (select row_number() over(partition by id order by Date) as rowid,
               id,
               Date
        from   Table1 
        where  Date is NULL) T1

join   (select row_number() over(partition by id order by Date) as rowid,
               id,
               Date
        from   Table2) T2

on      T1.id    = T2.id
and     T1.rowid = T2.rowid;
Run Code Online (Sandbox Code Playgroud)

结果:

select * from Table1;

id  Date
--- --------------------
1   2013-01-29T08:50:00Z
1   2013-01-29T15:28:00Z
2   2013-01-31T11:56:00Z
2   2013-01-31T14:04:00Z
2   2013-03-11T16:08:00Z
Run Code Online (Sandbox Code Playgroud)

这是上述的SQL Fiddle