Atualizar tabela usando valores de outra tabela no SQL Server


13

Eu tenho 2 tabela no meu banco de dados.

Tabela 1

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

Mesa 2

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

na tabela nº 1, o endereço das colunas e phone2 está vazio e os valores de sexo e data de nascimento das colunas são os mesmos da tabela nº 2.

Como posso ler dados da tabela 2 e atualizar o endereço e telefone2 na tabela 1 com valores das colunas de endereço e telefone da tabela 2 quando sexo e data de nascimento são iguais em cada linha?

por exemplo: esses são alguns dados da Tabela 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|
-------------------------------------------------------------------------

e aqui estão alguns dados na tabela # 2

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

Quero atualizar a tabela 1 com os dados da tabela 2, verificar o sexo e a data de nascimento e criar a tabela 1 como

-------------------------------------------------------------------------
| 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|
-------------------------------------------------------------------------

Como posso fazer isso?


11
E se houver 2 ou mais pessoas com o mesmo sexo e data de nascimento? Qual telefone e endereço (dentre muitos) devem ser copiados?
— ypercubeᵀᴹ

não é possível, é apenas uma tabela de teste; nos meus dados reais não é possível que a mesma pessoa tenha os mesmos valores.
— John Doe

Se isso realmente não for possível, ou seja, se houver uma UNIQUErestrição table2 (gender, birthdate), você deve adicionar essa informação na pergunta.
— ypercubeᵀᴹ

Respostas:


26

Existem algumas maneiras de alcançar os resultados desejados.

Métodos indeterministas

(no caso de muitas linhas na tabela 2 corresponderem a uma na tabela 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

Ou uma forma um pouco mais concisa

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

Ou com um 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 

Métodos determinísticos

MERGE lançaria um erro em vez de aceitar resultados não determinísticos

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; 

Ou você pode escolher um registro específico se houver mais de uma correspondência

Com 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 

.. Ou um 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;

Obrigado pela sua grande ajuda! Eu tenho 2 perguntas: 1) Eu acho que é uma maneira simples de fazer isso, acho que dessa forma diminui o desempenho e se eu tiver cerca de 50milhões de registros dessa maneira, é muito lento, você concorda? 2) dessa forma, se eu quiser ingressar na 2table e algumas colunas da tabela 2 não existirem na tabela 1, obtive algum erro? por exemplo, se eu tiver uma coluna de cores na tabela 2 e não existir na tabela 1, o processo de junção obteve erro ou apenas as colunas de junção existem em 2tables? Obrigado mais uma vez ...
— John Doe

11
@JohnDoe se você tiver uma pergunta sobre desempenho, faça uma nova pergunta e forneça detalhes sobre o tamanho da tabela, estruturas, índices e planos de execução. Não entendo o que você está perguntando no ponto 2, edite sua pergunta e forneça estruturas de tabela de exemplo que demonstrem o problema que você está perguntando.
— Martin Smith

11
@ JohnDoe: se você quer dizer com coluna, quer dizer um valor de coluna (em outras palavras, uma linha correspondente ) - quando não há linha correspondente, nenhum erro é gerado. No caso de uma junção interna (como aqui), as linhas não correspondentes simplesmente não serão atualizadas. Mas se você realmente quis dizer uma coluna que existe em uma tabela e não existe na outra, acredito que nova pergunta a ser feita separadamente.
— Andriy M

Nesse primeiro CTE, como o SQL Server sabe qual tabela atualizar?
— RonJohn

@RonJohn Ele conhece a fonte das colunas. ou seja, que ambos tgt_addresse tgt_phonesão aliases para colunas em #Table1- de modo que é o destino da atualização.
— Martin Smith

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

Os nomes dos campos na resposta não correspondem aos nomes dos campos na pergunta, mas a técnica funciona.
— RonJohn

Graças Ron, apenas dando a ideia
— David Fawzy

Ele é , no entanto, por que a sua resposta foi rejeitada.
— 31419 RonJohn

Graças não tem certeza, código como eu copiei estava trabalhando na minha candidatura ao vivo
— David Fawzy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.