SQL Serverの別のテーブルの値を使用してテーブルを更新する


13

データベースに2つのテーブルがあります。

表1

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

テーブル#2

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

テーブル#1の列ではaddressphone2は空で、列の性別生年月日の値はテーブル#2と同じです。

どのように私はテーブル#2及び更新からデータを読み取ることができますアドレスphone2のテーブル#2からの値を持つテーブル#1でのアドレス電話するとき、列を性別誕生日が各行に同じですか?

例:これは表#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  |
-----------------------------------------

テーブル#1をテーブル#2のデータで更新し、性別誕生日をチェックして、テーブル#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
そして、同じ性別と生年月日を持つ2人以上の人がいる場合はどうなりますか?コピーする必要があるのは、(多くの)どの電話とアドレスですか。
ypercubeᵀᴹ

それは不可能です。これは単なるテストテーブルです。私の実際のデータでは、同じ人物が同じ値を持つことはできません。
John Doe

それが本当に不可能な場合、つまりにUNIQUE制約がtable2 (gender, birthdate)ある場合は、その情報を質問に追加する必要があります。
ypercubeᵀᴹ

回答:


26

希望する結果を得るには、いくつかの方法があります。

不確定な方法

(テーブル2の多くの行がテーブル1の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)これは簡単な方法だと思います。これはパフォーマンスを低下させることだと思います。約50百万のレコードがある場合、この方法は非常に遅いと思いますか。2)このように、2tableを結合し、テーブル#2の一部の列がテーブル#1に存在しない場合、エラーが発生しますか?たとえば、テーブル#2にカラー列があり、それがテーブル#1に存在しない場合、結合プロセスでエラーが発生するか、2つのテーブルに結合列が存在するだけですか?ありがとうございました...
John Doe

1
@JohnDoeパフォーマンスに関する質問がある場合は、新しい質問をして、テーブルサイズ、構造、インデックス、実行計画の詳細を提供してください。ポイント2であなたが何を求めているのか理解できません。質問を編集し、あなたが求めている問題を実証するテーブル構造の例を提供してください。
マーティン・スミス

1
@JohnDoe:列とは、列の(つまり、一致する行)を意味します。一致する行がない場合、エラーは発生しません。内部結合(ここのような)の場合、一致しない行は更新されませんが、実際に1つのテーブルに存在し、もう1つのテーブルには存在しないを意味している場合、それは1つだと思います別途質問する新しい質問。
Andriy M 2016

その最初のCTEで、SQL Serverはどのテーブルを更新するかをどのようにして知るのですか?
RonJohn、

@RonJohn列のソースを認識しています。つまり、その両方tgt_addresstgt_phoneの列の別名です#Table1-それは、更新の対象となるようにします。
マーティン・スミス

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

回答のフィールド名は質問のフィールド名と一致しませんが、手法は機能します。
RonJohn、

Ronに感謝します。アイデアを
教えてください

しかし、それあなたの回答が否決された理由です。
RonJohn

不明な点があります。コピーしたコードがライブアプリケーションで機能していたためです
David Fawzy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.