SQL UPDATE SET eine Spalte so einstellen, dass sie einem Wert in einer verwandten Tabelle entspricht, auf die von einer anderen Spalte verwiesen wird?

112

Ich hoffe, das hat Sinn gemacht, lassen Sie mich näher darauf eingehen:

Es gibt eine Tabelle mit Tracking-Daten für ein Quizprogramm, in dem jede Zeile ..

QuestionID und AnswerID (es gibt jeweils eine Tabelle). Aufgrund eines Fehlers wurden einige QuestionIDs auf NULL gesetzt, aber die QuestionID einer verwandten AnswerID befindet sich in der Answers-Tabelle.

Angenommen, QuestionID ist NULL und AnswerID ist 500. Wenn wir in der Tabelle Answers nach AnswerID 500 suchen, gibt es eine Spalte mit der QuestionID, in der sich der NULL-Wert befinden sollte.

Im Grunde möchte ich festlegen, dass jede NULL-Frage-ID gleich der Frage-ID ist, die in der Antworttabelle in der Antwortzeile der Antwort-ID in der Verfolgungstabelle gefunden wird (dieselbe Zeile wie die NULL-Frage-ID, die geschrieben wird).

Wie würde ich das machen?

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

Ich bin mir nicht sicher, wie ich die QuestionID aus der passenden AnswerID der QuestionID zuweisen kann ...

CloudMeta
quelle
MySQL und Microsoft SQL Server unterstützen jeweils Erweiterungen der SQL-Syntax, um UPDATE mit mehreren Tabellen zu unterstützen. Andere Marken nicht. Sie haben nicht angegeben, welche Datenbankmarke Sie verwenden.
Bill Karwin

Antworten:

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

Ich empfehle, vor dem Ausführen des Updates zu überprüfen, welche Ergebnismenge aktualisiert werden soll (dieselbe Abfrage, nur mit einer Auswahl):

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

Insbesondere, ob jeder Antwort-ID definitiv nur eine Frage-ID zugeordnet ist.

eglasius
quelle
7
Ich bin mir nicht sicher warum, aber das funktioniert bei mir nicht, aber das funktioniert: update QuestionTrackings q inner join QuestionAnswers a on q.AnswerID = a.AnswerID set q.QuestionID = a.QuestionID; scheint dieselbe grundlegende Abfrage in einer anderen Reihenfolge zu sein. Irgendeine Idee warum?
Billynoah
2
@billynoah, ORA-00971: fehlendes SET-Schlüsselwort in Oracle
masT
2
Ein Problem mit einer ähnlichen Situation in PhpMyAdmin über MySQL. In meinem Fall befinden sich die Quell- und Zielspalten in derselben Tabelle, die Datensatzauswahl basiert jedoch auf der anderen Tabelle. Die "SELECT" -Version der Abfrage funktioniert, aber die UPDTATE-Anweisung löst einen Syntaxfehler bei "FROM"
2NinerRomeo
3
Ich habe mein Problem UPDATE table1 NATURAL JOIN table2 SET table1.col1 = table1.col2 WHERE table2.col3 ="condition"
überwunden,
Ist "q" von "update q" in der Antwort ein wörtlicher Abfrageparameter oder ist es nur Ihre Abkürzung für einen Tabellennamen?
Shawn
28

Verwenden Sie ohne die Update-and-Join-Notation (nicht alle DBMS unterstützen dies):

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)

In einer solchen Abfrage müssen Sie die WHERE-Klausel häufig mit einer EXISTS-Klausel qualifizieren, die die Unterabfrage enthält. Dies verhindert, dass das UPDATE über Zeilen trampelt, in denen keine Übereinstimmung vorliegt (normalerweise werden alle Werte auf Null gesetzt). In diesem Fall spielt es wohl keine Rolle, da eine fehlende Fragen-ID NULL in NULL ändern würde.

Jonathan Leffler
quelle
Diese Methode funktionierte für mich unter Oracle 12c (wo die Update-Join-Methode fehlgeschlagen ist).
Shwartz
16

Ich weiß nicht, ob Sie auf MySQL Workbench auf dasselbe Problem gestoßen sind wie ich, aber das Ausführen der Abfrage mit der INNER JOINAfter- FROMAnweisung hat bei mir nicht funktioniert. Ich konnte die Abfrage nicht ausführen, da sich das Programm über die FROMAnweisung beschwert hat .

Damit die Abfrage funktioniert, habe ich sie in geändert

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

anstatt

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

Ich denke, meine Lösung ist die richtige Syntax für MySQL.

AxeEffect
quelle
Ja, sieht aus wie für MySQL, der JOIN wird als Teil des Teils 'table_references' einer Abfrage betrachtet. MySQL Join
AWP
12
UPDATE
    "QuestionTrackings"
SET
    "QuestionID" = (SELECT "QuestionID" FROM "Answers" WHERE "AnswerID"="QuestionTrackings"."AnswerID")
WHERE
    "QuestionID" is NULL
AND ...
Milen A. Radev
quelle
1
Arbeitete für mich am Orakel. @ eglasius Antwort hat nicht.
Lombas
7

Ich hatte die gleiche Frage. Hier ist eine funktionierende Lösung, die der von eglasius ähnelt. Ich benutze postgresql.

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

Es wird beanstandet, ob q anstelle des Tabellennamens in Zeile 1 verwendet wurde und der Frage-ID in Zeile 2 nichts vorausgehen sollte.

Geist beleuchten
quelle
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;
Frank
quelle
3

Für MySQL können Sie diese Abfrage verwenden

UPDATE Tabelle1 a, Tabelle2 b SET a.coloumn = b.coloumn WHERE a.id = b.id.

Samir Patel
quelle
1

Aktualisieren Sie die Daten der 2. Tabelle in der 1. Tabelle, um sie vor SET zu verbinden:

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

unten funktioniert für MySQL

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

Ich denke das sollte funktionieren.

UPDATE QuestionTrackings
SET QuestionID = (SELECT QuestionID
                  FROM AnswerTrackings
                  WHERE AnswerTrackings.AnswerID = QuestionTrackings.AnswerID)
WHERE QuestionID IS NULL
AND AnswerID IS NOT NULL;
Anfänger
quelle