# MYSQL: Update mit werten aus anderer Tabelle



## Opor (11. Oktober 2004)

* MYSQL 4.0.16: Update mit werten aus anderer Tabelle*

Hallo,

ich habe folgendes Problem:
Ich habe 2 Tabellen:
-> User und Order
In der Tabelle User sind alle Nutzer gespeichert.
In der Tabelle Bestellungen sind beliebig viele die Bestellung verschiedener Nutzer. Es kann aber auch ein Nutzer mehrere Bestellungen haben.
In der Tabelle User existiert eine Uid welche auch in der Tabelle Bestellung logischerweise existiert.

Ich möchte nun per UPDATE den Wert createDate in der Tabelle User ändern.
Der Wert in den geändert wird stammt aus der Tabelle Bestellungen. Er ist das kleinste Datum aus der Tabelle Bestellungen. 

Ich habe schon einiges ausprobiert, doch leider bin ich immernoch nicht zu einem Ergebnis gekommen.
Es handelt sich um eine MYSQL Datenbank!

So ungefähr sollte es aussehen:
UPDATE user,order SET user.createDate = Min( order.orderDate ) WHERE user.Uid = order.Uid

Vielen Dank für eure Hilfe


----------



## Opor (11. Oktober 2004)

Kann mir denn niemand mal einen Tipp geben, wie es funktionieren könnte


----------



## ManicMarble (11. Oktober 2004)

Hallo Opor,

zunächst mal: Updates über mehrere Tabellen sind grundsätzlich "tricky" (siehe dazu die MySQL-Doku, speziell die Kommentare).

Dann: Der Tabellen-Name "order" ist nicht sehr empfehlenswert, da der Interpreter diesen Namen gerne mit dem ORDER BY verwechselt, ergo muss der Tabellenname order immer als `order` geschrieben werden, sonst droht Syntax-Error.

Ein weiteres Problem ist die Gruppen-Funktion MIN() ohne GROUP BY.

So, jetzt 2 Lösungsvorschläge, einmal mit SubQuery (ab MySQL 4.1):

```
UPDATE
 user AS u
LEFT JOIN
 (SELECT uid, MIN(datum) AS mindatum FROM `order` GROUP BY uid) AS o ON u.id = o.uid
SET
 u.createDate = o.mindatum
```
und einmal mit temporärer Tabelle (MySQL 4.0 und früher):

```
DROP TABLE IF EXISTS tmp_order;

CREATE TEMPORARY TABLE tmp_order TYPE = HEAP
 SELECT uid, MIN(datum) AS mindatum FROM `order` GROUP BY uid;

UPDATE
 user
LEFT JOIN
 tmp_order ON user.id = tmp_order.uid
SET
 user.createDate = tmp_order.mindatum;

DROP TABLE IF EXISTS tmp_order;
```
Vielleicht hilft's.
Grüße,
Martin


----------



## Opor (12. Oktober 2004)

Vielen Dank,

hast mir mein größtes Problem aus dem Weg geschafft

Danke


----------



## steph (23. Januar 2010)

Hallo,

vielen Dank für diese Antwort - die hat mir auch sehr weitergeholfen.
Vorher habe ich immer nur dumme Kommentare und Verweise auf die Handbücher gefunden, in denen ein Beispiel dieser Art aber nicht enthalten ist.

VIELEN DANK nochmals 

grüße
steph.


----------



## Mc_Fly_B (10. März 2010)

Hallo,

habe auch ein ähnliches Problem. Ähnlich in dem Sinne, dass zusätzlich ein weiterer Wert in selbiger Tabelle von einer anderen Tabelle referenziert wird... kompliziert genug?!

Folgende Tabellen:
Beiträge (id_beitrag, id_thema, titel) t1
Themen (id_thema, id_erster_beitrag) t2

Beispielinhalte:
t1
1, 1, Irgendwas
2, 1,
3, 2, Nochwas
4, 3, Wieder was
5, 1,
6, 3,
usw.

t2
1, 1
2, 3
3, 4
usw.

Überall dort, wo auf Beiträge geantwortet wurde, stehen keine Titel drin. Dort soll aber der Titel jetzt geändert werden auf: "Antwort auf: " und dann der Titel des ersten Beitrags.
Also wenn t1.id_beitrag = t2.id_erster_beitrag bleibt titel oder noch besser anders herum: wenn t1.id_beitrag <> t2.id_erster_beitrag wird titel = "Antwort auf: ",(titel, wo id_beitrag = id_erster_beitrag ist)

Die erste Tabelle sollte danach so aussehen:
1, 1, Irgendwas
2, 1, Antwort auf: Irgendwas
3, 2, Noch was
4, 3, Wieder was
5, 1, Antwort auf: Irgendwas
6, 3, Antwort auf: Wieder was
usw.

Komme auch mit obigen Beispielen leider nicht weiter.

Mc Fly


----------



## Yaslaw (10. März 2010)

Auf die Schnelle gezimmert und nicht getestet könnte es ev. etwa so gehen.


```
SELECT
	antw.id_thema,
	antw.id_beitrag,
	CONCAT("Auntwort auf: ", erste.title) AS title
FROM
	(SELECT t1.id_beitrag, t1.id_thema
	FROM t1
	WHERE (t1.id_thema, t1.id_beitrag) NOT IN (SELECT t2.id_thema, t2.id_beitrag FROM t2)) AS antw,
	(SELECT t1.id_thema, t1.title
	FROM t1		
	WHERE (t1.id_thema, t1.id_beitrag) NOT IN (SELECT t2.id_thema, t2.id_beitrag FROM t2)) AS erste
WHERE
	antw.id_thema = erste.id_thema
UNION SELECT 
	t1.id_thema, 
	t1.id_beitrag,
	t1.title
FROM t1		
WHERE (t1.id_thema, t1.id_beitrag) NOT IN (SELECT t2.id_thema, t2.id_beitrag FROM t2)) AS erste
```


----------



## Mc_Fly_B (10. März 2010)

Auf die Schnelle übernommen und getestet ergab sich folgender Fehler:

#1064 ... syntax to use near ') AS erste LIMIT 0, 30' at line 19

Und wo t2.id_beitrag steht ist t2.id_erster_beitrag gemeint? Gehe ich mal von aus.

Mc Fly


----------



## Yaslaw (10. März 2010)

Hab am ende von C&P ein ') AS erste' zu viel (letzte Zeile)
Und ja, t2.id_erster_beitrag - natürlich


----------



## Mc_Fly_B (10. März 2010)

Nachdem ich noch Beiträge AS t1 und Themen AS t2 überall eingetragen hatte, lief es.

Brachte allerdings für title überall nur "Antwort auf: " und sonst nix, dafür aber auch gleich in doppelter Anzahl der zu behebenden Zeilen...  Genauer nachgeschaut: erste Hälfte des Ergebnisses "Antwort auf: ", zweite Hälfte ist title leer.
Die Abfrage nimmt sich also nicht den Titel aus dem ersten Beitrag, sondern den aus dem aktuellen.

Was mir gerade auffällt (soweit meine Logik am Morgen schon funktioniert...  ):
Tut's für die letzte, also äußere, Bedingung nicht auch ein simples:

```
WHERE t1.id_beitrag <> t2.id_erster_beitrag
```
Das Teil dauert nämlich reichlich lange...

Mc Fly


----------



## Mc_Fly_B (11. März 2010)

Also die beiden Abfragen um die Einzelergebnisse zu erhalten:

t1.id_beitrag mit leerem titel

```
SELECT t1.id_beitrag
FROM beitraege AS t1 , themen AS t2
WHERE t1.id_beitrag <> t2.id_erster_beitrag AND t1.id_thema = t2.id_thema;
```

titel von t2.id_thema

```
SELECT t1.titel
FROM beitraege AS t1 , themen AS t2
WHERE t1.id_beitrag = t2.id_erster_beitrag
```

Das muss doch recht simpel zu verknüpfen sein?!

Mc Fly


----------

