Alle Felder einer DB updaten für einen Zeitbereich

Nikolaus

Benutzer
Beiträge
8
Hallo,

Ich hab nicht allzuviel Erfahrung mit DB Änderungen, daher hier mein Problem:

Ich habe in einer MariaDB 2 Tabellen Tab1 und Tab2 mit identischen feldnamen (Incl. Feld DateTime).
Tab2 hat nur ein Subset des Zeitbereiches.
Ich möchte nun ALLE Felder der Tab1 aus den feldern von Tab2 updaten wenn:
WHERE Tab1.DateTime = Tab2.DateTime

Wie ist das UPDATE Statement hierfür?

Danke für Euren Support!
 
Werbung:
PS:
Ich habe dieses versucht:

UPDATE Zieltabelle
SET Zieltabelle.Spalte1 = Quelltabelle.Spalte1,
Zieltabelle.Spalte2 = Quelltabelle.Spalte2, ...
FROM Quelltabelle
WHERE Zieltabelle.DateTime = Quelltabelle.DateTime;

Hier erhalte ich den Fehler:
Fehler in der SQL-Abfrage (1064): Syntax error near 'FROM T_BKW_DC_COPY WHERE T_BKW_DC_COPY.DateTime = T_BKW_DC.DateTime' at line 23
 
Eigentlich sieht die Syntax richtig aus, zumindest in MSSQL müsste das so gehen. Ich bin aber nicht ganz sicher ob das bei MySQL genauso läuft. Eventuell hilft ein INNER JOIN, etwa so:
Code:
UPDATE Zieltabelle
SET Zieltabelle.Spalte1 = Quelltabelle.Spalte1,
Zieltabelle.Spalte2 = Quelltabelle.Spalte2, ...
FROM Zieltabelle
INNER JOIN Quelltabelle
ON Zieltabelle.DateTime = Quelltabelle.DateTime;
Abgesehen davon könnte noch ein Komma am Ende der letzten Zeile vor FROM stehen, das wäre auch ein Syntaxfehler an der genannten Stelle. Du hast die Liste der zu aktualisierenden Spalten ja etwas abgekürzt.
 
Danke für die umgehende Antwort!
Vor dem From habe ich KEIN Komma, das sollte also ok sein.
Auch das INNER JOIN hat die gleiche Fehlermeldung. Er stört sich scheinbar an dem FROM :-(

Die Query sieht so aus:
UPDATE T_BKW_DC
SET T_BKW_DC.U_DC1 = T_BKW_DC_COPY.U_DC1,
T_BKW_DC.I_DC1 = T_BKW_DC_COPY.I_DC1,
...
T_BKW_DC.Irrad3 = T_BKW_DC_COPY.Irrad3,
T_BKW_DC.MaxPower3 = T_BKW_DC_COPY.MaxPower3
FROM T_BKW_DC_COPY
WHERE (T_BKW_DC_COPY.DateTime = T_BKW_DC.DateTime) ;
 
Ja das scheint MySQL an der Stelle nicht zu unterstützen.

Mit einem Subselect im UPDATE-Teil dürfte es gehen. Nicht sehr elegant aber ich denke mal es geht um einen recht einmaligen Vorgang.
Code:
UPDATE T_BKW_DC
SET T_BKW_DC.U_DC1 = ( SELECT T_BKW_DC_COPY.U_DC1 FROM T_BKW_DC_COPY WHERE  T_BKW_DC_COPY.DateTime = T_BKW_DC.DateTime ),
...

PS: So ein Zeitstempel als Join-Kriterium ist auch so eine Sache, der kommt hoffentlich nie doppelt vor.
 
@castorp: Danke für die schnelle antwort.
So funktioniert es, allerdings sehr langsam.
Auf einem subset der DB (ca. 1% der daten) und nur einem Drittel der Feldänderungen
läuft die Query ca. 700 Sekunden.
Wie kann man beschleunigen?

UPDATE
Code:
UPDATE T_BKW_DC_SAVEPART,T_BKW_DC_COPY
SET T_BKW_DC_SAVEPART.U_DC1=T_BKW_DC_COPY.U_DC1,
   T_BKW_DC_SAVEPART.I_DC1 = T_BKW_DC_COPY.I_DC1,
    T_BKW_DC_SAVEPART.P_DC1 = T_BKW_DC_COPY.P_DC1,
    T_BKW_DC_SAVEPART.YieldDay1 = T_BKW_DC_COPY.YieldDay1,
    T_BKW_DC_SAVEPART.YieldTot1 = T_BKW_DC_COPY.YieldTot1,
    T_BKW_DC_SAVEPART.Irrad1 = T_BKW_DC_COPY.Irrad1,
    T_BKW_DC_SAVEPART.MaxPower1 = T_BKW_DC_COPY.MaxPower1
WHERE T_BKW_DC_SAVEPART.DateTime=T_BKW_DC_COPY.DateTime;
 
Wie genau stellst du denn sicher, das es ein Subset ist? Ich würde sagen Performance ganze Tabelle != Performance mit weiteren Einschränkungen.

Gibt es einen Index auf den Spalten DateTime in beiden Tabellen?
 
Danke für die Reaktion.
Einen Index gibt es in den tabellen nicht, wobei DateTime in beiden die gleichen Werte hat, da T_BKW_DC_SAVEPART eine Koie eines Subsets aus T_BKW_DC ist.
Zur Erklärung: In T_BKW_DCCOPY sind die Werte eines Balkonkraftwerkes (pro Minute) gespeichert.
Vor unserem Urlaub hatte ich die Sortware des Wechselrichters upgedated und nicht gesehen, dass ein Parameter
(in der mitte des JASON Strings) ergänzt wurde und daher ein Teil der Werte ab dem Update um ein Tabellenfeld verschoben waren.
Daher musste ich das Subset dieser Zeit als T_BKW_DC_SAVEPART kopieren und darin die Werte umsortieren.
Jetzt geht es darum, die geänderten Zeilen für gleiches DateTime wieder zurück zu kopieren.

Daher hatte ich es wie oen versucht, aber mit sehr schlechter Performance...
UPDATE T_BKW_DC_SAVEPART,T_BKW_DC_COPY
SET T_BKW_DC_SAVEPART.U_DC1=T_BKW_DC_COPY.U_DC1,
T_BKW_DC_SAVEPART.I_DC1 = T_BKW_DC_COPY.I_DC1,
....
WHERE T_BKW_DC_SAVEPART.DateTime=T_BKW_DC_COPY.DateTime;
Daher ist die Frage, wie ich evtl. in dem Update-Statement zunächst nur den Teil der Original-Tabelle T_BKW_DC_COPY
selektieren kann, um nur diesen Teil zu updaten.
PS: Ich habe absolut keine Erfahrung mit z.B. JOIN

Danke für eine potentielle bessere Lösung, ansonsten müsste ich mal den Rechner
für eine nacht beschäftigen und hoffen, dass er nicht aussteigt,
weil irgendwelche Ressourcen ausgehen ...
 
Also dein Query ist relativ simpel, da kann man nichts mehr dran optimieren aus meiner Sicht. Dein Query ist ein implizierter Join, weil FROM tabelle1, tabelle2 effektiv einen Join entspricht, dann tut das UPDATE tabelle1, tabelle2 auch.

Die Server Performance hängt natürlich von vielen Dingen ab (Hardware z.B. auch) und grade mit MySQL kenne ich mich wirklich nicht aus (gibt es noch verschiedene Engine's?). Aber ich glaube nicht, das es in deinem Interesse wäre, da jetzt groß was zu ändern.

Das einzige, von dem ich mir viel versprechen würde, wäre ein Index (oder eventuell auch zwei). Zumindest auf T_BKW_DC_SAVEPART.DateTime gehört aus meiner Sicht einer drauf, einfach mal erstellen und das selbe Statement nochmal absetzen und dann mit EXPLAIN (falls das unter MySQL so läuft) den Ausführungsplan anschauen.
 
1. Ich hab nicht alles verstanden, aber Du willst vielleicht nicht Millionen Datensätze updaten, sondern nur die, die falsch sind?
Das Statement von Castorp ändert alle Datensätze. Es könnte durch eine Bedingung geändert werden, sodass nur neue, falsche Datensätze der letzten Tage aktualisiert werden.
2. Bei dem beschriebenen Setting (Balkonkraftwerk) denke ich an eine DB, die mglw. auf einem Pi oder einem NAS (mit-)läuft, also minimale Ressourcen. Da kann man nicht viel Performance erwarten.

Also geduldig sein, Indizes anlegen auf dem Join Kriterium oder mal schauen, ob es Alternativen zu dem Statement (zu der Syntax) gibt, die bessere Ausführungspläne ergeben.

Grundsätzlich würde ich mich auch darum kümmern, ob der JSON String bzw. Dein Code vom Aufbau taugt, um mit Namen zu arbeiten (statt mit Positionen). Dann passieren solche Fehler gar nicht erst. Positional Parameter sind immer die schlechtere Wahl.

P.S.: ich habe den Teil mit den Angaben zu Deinem Rechner nun gesehen. Du vermutest selbst, dass er zu schlapp ist. Wenn Du eine alte Kiste für Dein Balkonkraftwerk verwertet hast, dann kann es natürlich auch dort zu solchen Problemen kommen, wie bei einem Pi.
Wenn die Gesamtleistung eines Systems schlecht ist, auch bedingt durch wenig Hauptspeicher, benötigen größere Updates u.U. vor allem frei verfügbaren Festplattenplatz.
 
Zuletzt bearbeitet:
Richtig,
Code:
UPDATE T_BKW_DC_SAVEPART,T_BKW_DC_COPY
SET T_BKW_DC_SAVEPART.U_DC1=T_BKW_DC_COPY.U_DC1,
T_BKW_DC_SAVEPART.I_DC1 = T_BKW_DC_COPY.I_DC1,
....
WHERE T_BKW_DC_SAVEPART.DateTime=T_BKW_DC_COPY.DateTime
AND (
T_BKW_DC_SAVEPART.U_DC1!=T_BKW_DC_COPY.U_DC1
OR T_BKW_DC_SAVEPART.I_DC1 != T_BKW_DC_COPY.I_DC1
OR...
);
könnte ein simpler Ansatz sein, nur geänderte Datensätze anzufassen. Ob das wirklich viel bringt ist schwer zu sagen.

Unter MSSQL gibt es noch MERGE, was ich selbst nicht mag und was es unter MySQL auch nicht gibt, aber es gibt einen Workaround der vielleicht Sinn macht:
 
Werbung:
Zurück
Oben