SQL UPDATE SET uma coluna para ser igual a um valor em uma tabela relacionada referenciada por uma coluna diferente?


112

Espero que tenha feito sentido, deixe-me explicar:

Há uma tabela de dados de rastreamento para um programa de teste em que cada linha tem ..

QuestionID e AnswerID (há uma tabela para cada um). Portanto, por causa de um bug, havia vários QuestionIDs definidos como NULL, mas o QuestionID de um AnswerID relacionado está na tabela de Respostas.

Então, digamos que QuestionID seja NULL e AnswerID seja 500, se formos para a tabela de Respostas e encontrarmos AnswerID 500, haverá uma coluna com QuestionID que deveria estar onde o valor NULL está.

Então, basicamente, eu quero definir cada QuestionID NULL para ser igual ao QuestionID encontrado na tabela Answers na linha Answer do AnswerID que está na tabela de rastreamentos (mesma linha que o QuestionID NULL que está sendo escrito).

Como eu faria isso?

UPDATE QuestionTrackings
SET QuestionID = (need some select query that will get the QuestionID from the AnswerID in this row)
WHERE QuestionID is NULL AND ... ?

Não tenho certeza de como serei capaz de atribuir o QuestionID ao QuestionID do AnswerID correspondente ...


MySQL e Microsoft SQL Server suportam extensões para sintaxe SQL para suportar UPDATE multi-tabela. Outras marcas não. Você não disse que tipo de banco de dados está usando.
Bill Karwin,

Respostas:


171
update q
set q.QuestionID = a.QuestionID
from QuestionTrackings q
inner join QuestionAnswers a
on q.AnswerID = a.AnswerID
where q.QuestionID is null -- and other conditions you might want

Eu recomendo verificar qual é o conjunto de resultados a ser atualizado antes de executar a atualização (mesma consulta, apenas com uma seleção):

select *
from QuestionTrackings q
inner join QuestionAnswers a
on q.AnswerID = a.AnswerID
where q.QuestionID is null -- and other conditions you might want

Particularmente se cada id de resposta tem definitivamente apenas 1 id de pergunta associado.


7
Não sei por que, mas isso não funciona para mim, no entanto: update QuestionTrackings q inner join QuestionAnswers a on q.AnswerID = a.AnswerID set q.QuestionID = a.QuestionID; parece ser a mesma consulta básica em uma ordem diferente. alguma ideia do porquê?
billynoah

2
@billynoah, ORA-00971: palavra-chave SET ausente no Oracle
masT

2
Tendo um problema com uma situação semelhante no PhpMyAdmin sobre MySQL. No meu caso, as colunas de origem e destino estão na mesma tabela, mas a seleção de registro é baseada na outra tabela. A versão "SELECT" da consulta funciona, mas a instrução UPDTATE lança um erro de sintaxe em "FROM"
2NinerRomeo

3
Eu UPDATE table1 NATURAL JOIN table2 SET table1.col1 = table1.col2 WHERE table2.col3 ="condition"
superei

é "q" de "update q" na resposta um parâmetro de consulta literal ou é apenas uma abreviação para um nome de tabela?
Shawn

28

Sem a notação update-and-join (nem todos os DBMS suportam isso), use:

UPDATE QuestionTrackings
   SET QuestionID = (SELECT QuestionID
                        FROM AnswerTrackings
                        WHERE AnswerTrackings.AnswerID = QuestionTrackings.AnswerID)
   WHERE QuestionID IS NULL
     AND EXISTS(SELECT QuestionID
                        FROM AnswerTrackings
                        WHERE AnswerTrackings.AnswerID = QuestionTrackings.AnswerID)

Freqüentemente, em uma consulta como esta, você precisa qualificar a cláusula WHERE com uma cláusula EXISTS que contém a subconsulta. Isso evita que o UPDATE atropele as linhas onde não há correspondência (geralmente anulando todos os valores). Nesse caso, como um ID de pergunta ausente mudaria o NULL para NULL, isso não importa.


Este método funcionou para mim no Oracle 12c (onde o método update-join falhou).
shwartz de

16

Não sei se você encontrou o mesmo problema que eu no MySQL Workbench, mas executar a consulta com o INNER JOINdepois da FROMinstrução não funcionou para mim. Não consegui executar a consulta porque o programa reclamou doFROM declaração.

Então, para fazer a consulta funcionar, mudei para

UPDATE table1 INNER JOIN table2 on table1.column1 = table2.column1
SET table1.column2 = table2.column4
WHERE table1.column3 = 'randomCondition';

ao invés de

UPDATE a
FROM table1 a INNER JOIN table2 b on a.column1 = b.column1
SET a.column2 = b.column4
WHERE a.column3 = 'randomCondition';

Acho que minha solução é a sintaxe certa para MySQL.


Sim, parece que para o Mysql, o JOIN é considerado parte da parte 'table_references' de uma consulta. MySQL Join
AWP

12
UPDATE
    "QuestionTrackings"
SET
    "QuestionID" = (SELECT "QuestionID" FROM "Answers" WHERE "AnswerID"="QuestionTrackings"."AnswerID")
WHERE
    "QuestionID" is NULL
AND ...

1
Trabalhou no oracle para mim. A resposta de @eyglasius não.
Lombas

7

Eu estava tendo a mesma pergunta. Aqui está uma solução de trabalho semelhante à de eglasius. Estou usando o postgresql.

UPDATE QuestionTrackings
SET QuestionID = a.QuestionID
FROM QuestionTrackings q, QuestionAnswers a
WHERE q.QuestionID IS NULL

Ele reclama se q foi usado no lugar do nome da tabela na linha 1 e nada deve preceder QuestionID na linha 2.


3
 select p.post_title,m.meta_value sale_price ,n.meta_value   regular_price
    from  wp_postmeta m 
    inner join wp_postmeta n
      on m.post_id  = n.post_id
    inner join wp_posts p
      ON m.post_id=p.id 
    and m.meta_key = '_sale_price'
    and  n.meta_key = '_regular_price'
     AND p.post_type = 'product';



 update  wp_postmeta m 
inner join wp_postmeta n
  on m.post_id  = n.post_id
inner join wp_posts p
  ON m.post_id=p.id 
and m.meta_key = '_sale_price'
and  n.meta_key = '_regular_price'
 AND p.post_type = 'product'
 set m.meta_value = n.meta_value;

3

Para Mysql, você pode usar esta consulta

ATUALIZAR tabela1 a, tabela2 b SET a.coloumn = b.coloumn ONDE a.id = b.id


1

A atualização dos dados da 2ª tabela na 1ª tabela precisa do Inner join antes de SET:

`UPDATE `table1` INNER JOIN `table2` ON `table2`.`id`=`table1`.`id` SET `table1`.`name`=`table2`.`name`, `table1`.`template`=`table2`.`template`;

1

abaixo funciona para mysql

update table1 INNER JOIN table2 on table1.col1 =  table2.col1
set table1.col1 =  table2.col2

0

Eu acho que isso deve funcionar.

UPDATE QuestionTrackings
SET QuestionID = (SELECT QuestionID
                  FROM AnswerTrackings
                  WHERE AnswerTrackings.AnswerID = QuestionTrackings.AnswerID)
WHERE QuestionID IS NULL
AND AnswerID IS NOT NULL;
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.