使用来自SQL Server中另一个表的值更新表


13

我的数据库中有2个表。

表格1

-------------------------------------------------------------------------
| name | family | phone | email | gender | phone2 | address | birthdate |
-------------------------------------------------------------------------

表#2

-----------------------------------------
| gender | address | phone | birthdate |
-----------------------------------------

在表#1的列地址PHONE2是空的和列性别生日的值是相同的表#2。

我怎样才能读取表#2和更新数据的地址PHONE2表#1的值从表#2 的地址电话列时,性别出生日期是各行中的一样吗?

例如:这是表#1中的一些数据

-------------------------------------------------------------------------
| name | family | phone | email | gender | phone2 | address | birthdate |
-------------------------------------------------------------------------
| john | doe    | 12345| t@t.com| Male  |         |         | 1980-01-01|
-------------------------------------------------------------------------
| mike | clark  | 65432| x@y.com| Male  |         |         | 1990-01-01|
-------------------------------------------------------------------------
| Sara | King   | 875465| a@b.com|Female|         |         | 1970-01-01|
-------------------------------------------------------------------------

这是表2中的一些数据

-----------------------------------------
| gender | address | phone | birthdate  |
-----------------------------------------
| Male   | 1704test|0457852|1980-01-01  |
-----------------------------------------
| Female | 1705abcs|0986532|1970-01-01  |
-----------------------------------------
| Male   | 1602cyzd|0326589|1990-01-01  |
-----------------------------------------

我想使用表#2中的数据更新表#1,并检查性别生日,并使表#1像

-------------------------------------------------------------------------
| name | family | phone | email | gender | phone2 | address | birthdate |
-------------------------------------------------------------------------
| john | doe    | 12345| t@t.com| Male   |0457852 |1704test | 1980-01-01|
-------------------------------------------------------------------------
| mike | clark  | 65432| x@y.com| Male   |0326589  |1602cyzd| 1990-01-01|
-------------------------------------------------------------------------
| Sara | King   | 875465| a@b.com|Female |0986532  |1705abcs| 1970-01-01|
-------------------------------------------------------------------------

我怎样才能做到这一点?


1
如果有两个或两个以上性别和出生日期相同的人怎么办?应该复制(多少个)电话和地址?
ypercubeᵀᴹ

这不可能,这仅仅是测试表,在我的真实数据中不可能对同一个人具有相同的值。
约翰·多伊

如果这实际上是不可能的,即如果存在UNIQUE约束table2 (gender, birthdate),则应在问题中添加该信息。
ypercubeᵀᴹ

Answers:


26

有很多方法可以达到您想要的结果。

不确定方法

(如果表2中的许多行与表1中的一行匹配)

UPDATE T1
SET    address = T2.address,
       phone2 = T2.phone
FROM   #Table1 T1
       JOIN #Table2 T2
         ON T1.gender = T2.gender
            AND T1.birthdate = T2.birthdate

或更简洁的形式

UPDATE #Table1
SET    address = #Table2.address,
       phone2 = #Table2.phone
FROM   #Table2
WHERE  #Table2.gender = #Table1.gender
       AND #Table2.birthdate = #Table1.birthdate 

或与CTE

WITH CTE
     AS (SELECT T1.address AS tgt_address,
                T1.phone2  AS tgt_phone,
                T2.address AS source_address,
                T2.phone   AS source_phone
         FROM   #Table1 T1
                INNER JOIN #Table2 T2
                  ON T1.gender = T2.gender
                     AND T1.birthdate = T2.birthdate)
UPDATE CTE
SET    tgt_address = source_address,
       tgt_phone = source_phone 

确定性方法

MERGE 会引发错误而不是接受不确定的结果

MERGE #Table1 T1
USING #Table2 T2
ON T1.gender = T2.gender
   AND T1.birthdate = T2.birthdate
WHEN MATCHED THEN
  UPDATE SET address = T2.address,
             phone2 = T2.phone; 

或者,如果有多个匹配项,则可以选择一个特定的记录

APPLY

UPDATE T1
SET    address = T2.address,
       phone2 = T2.phone
FROM   #Table1 T1
       CROSS APPLY (SELECT TOP 1 *
                    FROM   #Table2 T2
                    WHERE  T1.gender = T2.gender
                           AND T1.birthdate = T2.birthdate
                    ORDER  BY T2.PrimaryKey) T2 

..或CTE

WITH T2
     AS (SELECT *,
                ROW_NUMBER() OVER (PARTITION BY gender, birthdate ORDER BY primarykey) AS RN
         FROM   #Table2)
UPDATE T1
SET    address = T2.address,
       phone2 = T2.phone
FROM   #Table1 T1
       JOIN T2
         ON T1.gender = T2.gender
            AND T1.birthdate = T2.birthdate
            AND T2.RN = 1;

感谢您的大力帮助!我有2个问题:1)我认为这样做很简单,我认为这种方式会降低性能,如果我有大约5000万个记录,这种方式非常慢,您同意吗?2)这样,如果我想加入2table并且表#2中的某些列在表#1中不存在,我会遇到任何错误吗?例如,如果我在表#2中有颜色列,而在表#1中不存在该颜色列,则连接过程出错或仅2个表中存在连接列?再次感谢...
John Doe

1
@JohnDoe,如果您对性能有疑问,请提出一个新问题,并提供表大小,结构,索引和执行计划的详细信息。我不明白您在第2点中提出的问题,请编辑您的问题并提供示例表结构来演示您所要解决的问题。
马丁·史密斯

1
@JohnDoe:如果按列表示,则表示列(换句话说,就是匹配的行)–当没有匹配的行时,不会引发错误。如果是内部联接(如此处),则不匹配的行将不会被更新,但是如果您确实是说某个表中存在一个而另一表中不存在的列,那么我认为那是一个还有更多新问题要另行询问。
Andriy M

在第一个CTE上,SQL Server如何知道要更新的表?
罗恩·约翰(RonJohn)

@RonJohn它知道列的来源。即,tgt_address和和tgt_phone都是#Table1-中列的别名,因此是更新的目标。
马丁·史密斯,

0
UPDATE TS
SET TS.TaskFullAddress = L.FullAddress
FROM [dbo].[TaskOrders]   TS
INNER JOIN Locations L
ON  TS.ClientId  = L.ClientId;

答案中的字段名称与问题中的字段名称不匹配,但是该技术有效。
罗恩·约翰

感谢罗恩(Ron)提出的想法
David Fawzy

但是,这就是为什么您的答案被否决的原因。
罗恩·约翰

不确定,谢谢,因为我复制的代码正在我的实时应用程序中运行
David Fawzy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.