SQL UPDATE SET une colonne pour être égale à une valeur dans une table associée référencée par une colonne différente?

112

J'espère que cela a du sens, laissez-moi élaborer:

Il existe un tableau de données de suivi pour un programme de quiz où chaque ligne a ..

QuestionID et AnswerID (il y a un tableau pour chacun). Donc, à cause d'un bogue, il y avait un tas de QuestionIDs définis sur NULL, mais le QuestionID d'un AnswerID associé est dans le tableau Answers.

Donc, disons que QuestionID est NULL et AnswerID est 500, si nous allons à la table Answers et trouvons AnswerID 500, il y a une colonne avec le QuestionID qui aurait dû être là où la valeur NULL est.

Donc, fondamentalement, je veux définir chaque QuestionID NULL pour être égal au QuestionID trouvé dans le tableau Answers sur la ligne Answer de l'AnswerID qui se trouve dans la table de suivi (même ligne que le QuestionID NULL qui est en cours d'écriture).

Comment ferais-je ça?

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

Je ne sais pas comment je pourrai lui faire attribuer le QuestionID au QuestionID à partir du AnswerID correspondant ...

CloudMeta
la source
MySQL et Microsoft SQL Server prennent chacun en charge les extensions de la syntaxe SQL pour prendre en charge la mise à jour multi-tables. Les autres marques ne le font pas. Vous n'avez pas dit quelle marque de base de données vous utilisez.
Bill Karwin

Réponses:

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

Je recommande de vérifier le jeu de résultats à mettre à jour avant d'exécuter la mise à jour (même requête, juste avec une sélection):

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

En particulier, si chaque identifiant de réponse n'a définitivement qu'un seul identifiant de question associé.

Eglasius
la source
7
Je ne sais pas pourquoi mais cela ne fonctionne pas pour moi, mais cela fonctionne: update QuestionTrackings q inner join QuestionAnswers a on q.AnswerID = a.AnswerID set q.QuestionID = a.QuestionID; semble être la même requête de base dans un ordre différent. une idée pourquoi?
billynoah
2
@billynoah, ORA-00971: mot clé SET manquant dans Oracle
masT
2
Avoir un problème avec une situation similaire dans PhpMyAdmin sur MySQL. Dans mon cas, les colonnes source et destination sont dans la même table, mais la sélection des enregistrements est basée sur l'autre table. La version "SELECT" de la requête fonctionne, mais l'instruction UPDTATE renvoie une erreur de syntaxe à "FROM"
2NinerRomeo
3
J'ai surmonté mon problème en éliminant le "FROM". Cela ressemblait plus à ceci:UPDATE table1 NATURAL JOIN table2 SET table1.col1 = table1.col2 WHERE table2.col3 ="condition"
2NinerRomeo
"q" de "update q" dans la réponse est-il un paramètre de requête littéral ou est-ce simplement votre raccourci pour un nom de table?
Shawn
28

Sans la notation de mise à jour et de jointure (tous les SGBD ne le prennent pas en charge), utilisez:

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)

Souvent, dans une requête comme celle-ci, vous devez qualifier la clause WHERE avec une clause EXISTS qui contient la sous-requête. Cela empêche UPDATE de piétiner les lignes où il n'y a pas de correspondance (annulant généralement toutes les valeurs). Dans ce cas, étant donné qu'un ID de question manquant changerait NULL en NULL, cela n'a sans doute pas d'importance.

Jonathan Leffler
la source
Cette méthode a fonctionné pour moi sur Oracle 12c (où la méthode de mise à jour a échoué).
shwartz
16

Je ne sais pas si vous avez rencontré le même problème que moi sur MySQL Workbench, mais l'exécution de la requête avec INNER JOINl' FROMinstruction après l' instruction n'a pas fonctionné pour moi. Je n'ai pas pu exécuter la requête car le programme s'est plaint de la FROMdéclaration.

Donc, pour que la requête fonctionne, je l'ai changée en

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

au lieu de

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

Je suppose que ma solution est la bonne syntaxe pour MySQL.

AxeEffect
la source
Ouais, ressemble à Mysql, le JOIN est considéré comme faisant partie de la partie 'table_references' d'une requête. Rejoindre MySQL
AWP
12
UPDATE
    "QuestionTrackings"
SET
    "QuestionID" = (SELECT "QuestionID" FROM "Answers" WHERE "AnswerID"="QuestionTrackings"."AnswerID")
WHERE
    "QuestionID" is NULL
AND ...
Milen A. Radev
la source
1
J'ai travaillé sur oracle pour moi. La réponse de @ eglasius ne l'a pas fait.
Lombas
7

J'avais la même question. Voici une solution de travail similaire à celle d'eglasius. J'utilise postgresql.

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

Il se plaint si q a été utilisé à la place du nom de table à la ligne 1, et que rien ne doit précéder QuestionID à la ligne 2.

Éclairer les esprits
la source
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;
Franc
la source
3

Pour Mysql, vous pouvez utiliser cette requête

UPDATE table1 a, table2 b SET a.coloumn = b.coloumn WHERE a.id = b.id

Samir Patel
la source
1

Mettre à jour les données de la 2ème table dans la 1ère table doivent être jointes internes avant SET:

`UPDATE `table1` INNER JOIN `table2` ON `table2`.`id`=`table1`.`id` SET `table1`.`name`=`table2`.`name`, `table1`.`template`=`table2`.`template`;
Santosh Singh
la source
1

ci-dessous fonctionne pour mysql

update table1 INNER JOIN table2 on table1.col1 =  table2.col1
set table1.col1 =  table2.col2
Pravin
la source
0

Je pense que cela devrait fonctionner.

UPDATE QuestionTrackings
SET QuestionID = (SELECT QuestionID
                  FROM AnswerTrackings
                  WHERE AnswerTrackings.AnswerID = QuestionTrackings.AnswerID)
WHERE QuestionID IS NULL
AND AnswerID IS NOT NULL;
Noob
la source