# [mySQL 5] Abfrage über mehrere Spalten - Ziel mehrere Spalten



## Mc_Fly_B (1. März 2010)

... und blutiger Anfänger. 

Moin erstmal!

Habe eine Tabelle _ge_board_content_ mit den Spalten _*content_id*_, _board_id_, _parent_content_id_,_ user_id_, _reply_to_ und _views_ und weiteren.
Eine weitere Tabelle _topics_ mit den Spalten _*id_topic*_, _id_board_, _id_first_msg_, _id_member_started_ und _num_views_ und weiteren.
Die fett geschriebenen sind PRIMARY und auto-increment. Gebe hier nur Spalten an, die vorerst wichtig erscheinen.

Nun soll _topics.id_topic_ als sich erhöhender Zähler dienen. _topics.id_board_ soll mit _ge_board_content_, _topics.id_first_msg_ soll mit _ge_board_content.content_id_, _topics.id_member_startet_ mit _ge_board_content.user_id_ und _topics.num_views_ mit _ge_board_content.views_ befüllt werden, wenn _ge_board_content.parent_content_id_ und _ge_board_content.reply_to_ gleich "0" sind.

Ein erster Versuch mit nur einer Spalte:

```
INSERT INTO topics( `id_first_msg` )
SELECT content_id FROM ge_board_content
WHERE((`ge_board_content`.`parent_content_id` =0)AND(`ge_board_content`.`reply_to` =0))
```

brachte die Fehlermeldung: #1062 - Duplicate entry '0-0' for key 2

Zumindest ist der Inhalt in der ersten Zeile korrekt. Nur wo hakt es? Und wie bekomme ich die anderen Spalten möglichst in einem Rutsch gefüllt? Und das ist auch nur der Anfang.

Mc Fly


----------



## Mc_Fly_B (2. März 2010)

Gebe ich mehrere Spalten im INSERT INTO an:

```
INSERT INTO topics ( `id_board`, `id_first_msg`, `id_member_started`, `num_views` )
SELECT board_id,content_id,user_id,views FROM ge_board_content
WHERE((`ge_board_content`.`parent_content_id` = 0) AND (`ge_board_content`.`reply_to` = 0))
```
ergibt das die Fehlermeldung: #1062 - Duplicate entry '0-7' for key 2

Das liegt offensichtlich an der Spalte _topics.id_last_msg_. Diese ist im Bezug auf _topics.board_id_ auf UNIQUE gesetzt. Gleiches gilt auch für _topics.id_first_msg_. Ich muss also vorher noch den letzten Eintrag finden. Wenn ich da richtig liege, darf ich erst _ge_board_content.parent_content_id_ mit der letzten Zeitangabe in _ge_board_content.creation_datetime_ finden. Gleichzeitig kann ich auch noch _ge_board_content.parent_content_id_ zählen und in _topics.num_replies_ ablegen. Ich weiß aber erst nach dem WHERE um welche _ge_board_content.content_id_ es sich handelt, die ich nach dem letzten Eintrag abfragen und auch zählen kann.

Ich hatte ja schon befürchtet, dass es kompliziert wird... 

Mc Fly


----------



## Yaslaw (2. März 2010)

Kompliziert ist es nicht unbedingt. Ich versteh nur noch nicht was du da machen willst.


----------



## Mc_Fly_B (2. März 2010)

Die erste Tabelle ist so ein Forum unbekannten Formats. Wurde mal irgendwann von jemandem selbst verfasst. Ist absolut nicht mehr up-to-date.

Die zweite Tabelle ist die smf_topics von SMF2. Und da sollen nun die Verlinkungen zum Inhalt (smf_messages) aus dem alten Forum hinein. Also im Grunde eine "simple" Konvertierung. Wobei der Inhalt aus dem alten Forum in einer Tabelle liegt, inklusive der Board- und Topic-Angaben, während es in SMF2 getrennt in zwei Tabellen liegt. Der Inhalt selbst machte weniger Schwierigkeiten.

Mc Fly


----------



## Mc_Fly_B (2. März 2010)

Lasse ich die fehlerhafte zweite Anweisung durchlaufen, habe ich zumindest schon mal zwei Zeilen in der _topics_.

Damit kann ich schon mal die Abfrage zum Zählen testen:

```
SELECT `topics`.`id_first_msg`,COUNT(*)
FROM `ge_board_content`,`topics`
WHERE `ge_board_content`.`parent_content_id`=`topics`.`id_first_msg`
GROUP BY `topics`.`id_first_msg`
```
Funktioniert...  Liefert zwei korrekte Ergebnisse die ich in `topics`.`num_replies` einfügen kann.

Nun zum Lokalisieren des letzten Eintrags... wir schreiten voran.

Mc Fly


----------



## Mc_Fly_B (2. März 2010)

Letzter Eintrag ist auch gefunden:


```
SELECT `parent_content_id` , `content_id` , MAX( `creation_datetime` )
FROM `ge_board_content`
WHERE `parent_content_id` <> 0
GROUP BY `parent_content_id`
```

Habe Stichproben per Hand überprüft: Stimmt! 

Und nun den ganzen Abfragenwust zu einem Stück verschmelzen...  ... arbeite mich weiter voran.

Mc Fly


----------



## Mc_Fly_B (3. März 2010)

Stehe jetzt etwas auf dem Schlauch. Sehe den Wald vor lauter Bäumen nicht mehr... 

Wie bekomme ich den Wert für _`ge_board_content`.`content_id`_ aus dieser Abfrage:

```
SELECT `parent_content_id` , `content_id` , MAX( `creation_datetime` )
FROM `ge_board_content`
WHERE `parent_content_id` <> 0
GROUP BY `parent_content_id`
```

als _`topics`.`id_last_msg`_ in diese INSERT INTO:

```
INSERT INTO topics ( `id_board`, `id_first_msg`, `id_last_msg`, `id_member_started`, `num_views` )
```

Mir qualmt so langsam der Schädel... 

Mc Fly


----------



## Mc_Fly_B (3. März 2010)

Bin jetzt doch einigermaßen verwirrt!

Folgende Abfrage brachte korrekte Ergebnisse bezüglich des Datums des letzten Eintrags für ein Topic:

```
SELECT `parent_content_id` , MAX( `creation_datetime` )
FROM `ge_board_content`
GROUP BY `parent_content_id`
```

Da ich aber zur Weiterverarbeitung noch die _`content_id`_ dazu benötige aber die "0"-Einträge von _`parent_content_id`_ nicht, habe ich diese Abfrage erweitert:

```
SELECT `parent_content_id` , `content_id` , MAX( `creation_datetime` )
FROM `ge_board_content`
WHERE `parent_content_id` <> 0
GROUP BY `parent_content_id`
```

Diese Abfrage bringt mir zwar immer noch das letzte Datum, aber dieses passt nicht zu _`content_id`_!?

Ok! Habe noch etwas probiert:

```
SELECT `parent_content_id` , MAX( `content_id` ) , MAX( `creation_datetime` )
FROM `ge_board_content`
WHERE `parent_content_id` <> 0
GROUP BY `parent_content_id`
```

Auch hier passt das Ergebnis nicht, da das alte System offensichtlich die IDs von gelöschten Einträgen wieder verwendet hat... 

Mc Fly


----------



## Mc_Fly_B (4. März 2010)

Zur Umgehung der Schlüssel habe ich mir damit geholfen, dass ich, anstatt den letzten Eintrag abzufragen, erstmal den ersten dort rein gesetzt habe:

```
INSERT INTO topics ( `id_board`, `id_first_msg`, `id_last_msg`, `id_member_started`, `num_views` )
SELECT board_id,content_id,content_id,user_id,views FROM ge_board_content
WHERE((`ge_board_content`.`parent_content_id` = 0) AND (`ge_board_content`.`reply_to` = 0))
```

Will ich nun die letzten Einträge berechnen, liefert mir z. B. :

```
SELECT `content_id`
FROM `ge_board_content`
WHERE (SELECT MAX(`creation_datetime`)
              FROM `ge_board_content`
              ) AND `parent_content_id` <> 0
GROUP BY `parent_content_id`
```

genau eine Spalte mir den benötigten und korrekten Werten zurück.

Wie bekomme ich diese Werte nun an die richtige Stelle?

```
UPDATE smf_topics , ge_board_content
SET smf_topics.id_last_msg = ge_board_content.content_id
WHERE (SELECT MAX(`creation_datetime`)
              FROM `ge_board_content`
              WHERE `parent_content_id` <> 0
GROUP BY `parent_content_id`)
```

Funktioniert ja nicht, da logischerweise Fehlermeldung #1242 - Subquery returns more than 1 row

Mc Fly


----------

