SQL Sub-Select liefert Fehler: Unable to save result set

C

Cave Johnson

Gast
Hi,

ich möchte bei einer MySQL-DB mittels Sub-Select Daten abfragen, bekomme aber einen Fehler: Unable to save result set.

Die Tabellen sehen so aus:

T1:
Code:
| id | code   |
|  1 | 12345  |
|  2 | 23456  |
|  3 | 34567  |
|  4 | 12345  |
|  5 | 34567  |

T2:
Code:
| id | code_id | dauer |
|  1 |  1      | 342   |
|  2 |  3      | 122   |
|  3 |  2      | 232   |
|  4 |  1      | 534   |
|  5 |  4      |  97   |
|  6 |  3      | 113   |

Über den 'code' möchte ich die durchschnittliche 'dauer' ermitteln.

PHP:
SELECT AVG(dauer) AS dauer FROM T2 WHERE code_id = (SELECT id FROM T1 WHERE code = 12345)

Beim Query kommt dann besagter Fehler. Google sagt mir, dass evtl. die DB beschädigt ist; reparieren über PHPMyAdmin hat aber nicht geholfen.

Woran liegts?
 
Zuletzt bearbeitet: (Beitrag wiederhergestellt)
Hast du's mal mit nem JOIN versucht, denn ich bin mir nicht sicher, ob man ein SELECT so bauen kann, wie du es da gemacht hast (aber das muss nichts heißen). Ich hab irgendwo im Hinterkopf, dass du noch ein GROUP brauchst (auch das muss nichts heißen)

also:
JOIN T1 mit T2 , WHERE T1.id = T2.code_id
dann darauf ein SELECT ... WHERE code = 12345
etc.
 
Die Tutorials die ich zu Join finde, sind in etwa so genau und ausführlich, wie dein Beispiel ;)

Wie müsste das denn aussehen?

PHP:
SELECT AVG(T2.dauer) AS dauer
FROM T2
INNER JOIN T1 ON (T2.code_id = T1.id)
WHERE T1.code = 12345
liefert lediglich einen Wert statt zwei, und den ich auch nicht nachvollziehen kann. Es ist weder der Avg von code_id = 1 noch von code_id = 4.
 
Zuletzt bearbeitet:
Ich werd mal eben meine Datenbank anwerfen und es ausprobieren :D

Ich hab in meiner Bilderdatenbank gerade das probiert und es ging problemlos:
Code:
SELECT AVG( photography.image_id ) 
FROM photography
JOIN photography_gallery ON photography_gallery.gallery_id = photography.gallery_id
WHERE photography_gallery.gallery_id =3

Auf deine Datenbank bezogen wär das dann:
Code:
SELECT AVG( T2.dauer ) 
FROM T1
JOIN T2 ON T1.id = T2.code_id
WHERE T1.code =12345

Die Schreibweise mit dem Punkt zwischen Tabelle und Attribut ist eigentlich nur nötig, wenn in beiden Tabellen die selben Attribute vorhanden sind. Ich hab sie bei dir drin gelassen, damit man sofort sieht was woher kommt. ;)

EDIT 2.5: In deinem Fall kannst du natürlich auch INNER JOIN benutzen. Das sollte beim Vergleich von genau einem Attribut soweit ich mich erinnern kann identisch sein.

Und der Tipp von Krafty (unter mir) ist natürlich gut zum debuggen:
Code:
SELECT *
FROM T1
JOIN T2 ON T1.id = T2.code_id
WHERE T1.code =12345
Dann siehst du schonmal was überhaupt alles betrachtet wird. Evtl. auch mal den ganzen WHERE-Teil weglassen, dann hast du den kompletten JOIN im Blick :)
 
Zuletzt bearbeitet:
Wenn du das AVG weglässt, sollte dir klar werden, welche Werte dort überhaupt genommen werden.
Am besten du lässt dir dazu noch die code_id anzeigen.
 
Das liefert leider denselben Wert wie bei meinem Versuch - den Avg von allen code_id = 1 und = 4.

Ich möchte aber 2 Werte, einmal den Avg von code_id = 1 und einmal den Avg von code_id = 4.
 
Aber du sagst doch am Ende deines Befehls: WHERE code_id = 12345
Damit sollte klar sein, dass er dir nur die Datensätze zu dieser einen Code-ID ausspuckt. Wenn du alle auf einmal haben möchtest, dann brauchst du ein GROUP BY:

Code:
SELECT T2.code_id, AVG( T2.dauer ) 
FROM T1
JOIN T2 ON T1.id = T2.code_id
GROUP BY T2.code_id

Damit gruppiert er alle Einträge nach code_id und bildet von den Gruppen jeweils den AVG Wert


EDIT: Jetzt versteh ich erst was du meinst :D
Du willst also einmal mit WHERE code = 12345 auf code_id 1 und 4 zugreifen und dann diese jeweils gruppieren :D
Ich schau nochmal drüber
 
Zuletzt bearbeitet:
Ich will aber nicht alle Mittelwerte. Nur dort, wo der code = 12345 ist, aber aufgetrennt nach id :)
 
Jap. hier ist die Lösung:

Code:
SELECT T2.code_id, AVG( T2.dauer ) 
FROM T1
JOIN T2 ON T1.id = T2.code_id
WHERE T1.code = 12345
GROUP BY T2.code_id

Das sollte es nun tun :D
Was es tut:
1. Kartesisches Produkt aus T1 und T2 (also JOIN) anhand von T1.id = T2.code_id
2. von diesem Ergebnis nur die behalten, wo T1.code = 12345
3. dieses Ergebnis gruppieren nach T2.code_id
4. von den Gruppen jeweils T2.code_id und AVG(T2.dauer) selektieren und zurückgeben


correctus maximus est?


EDIT: Nicht dass hier Verwirrung aufkommt: Die obengenannten Schritte sind für einen Menschen zum Verstehen! Die Datenbank macht das intern noch ein wenig anders:
Zuerst wird eigentlich das WHERE ausgeführt, da so der Datensatz extrem minimiert wird.
Danach werden nur noch die Daten geJOINt, die im SELECT stehen (und evtl. im GROUP, da diese nicht im SELECT enthalten sein müssen).
etc. pp.
 
Zuletzt bearbeitet:
Wunderbar, danke, das klappt. :)

Ich hatte es eben mit WHERE T2.code_id = 12345 versucht, was aber gar nichts ausspuckt ...
 
Ja, schau mal in deine T2 Tabelle, da gibt's keine code_id mit Nummer 12345 ;)
 
Dann noch viel Spaß mit deiner Datenbank und falls es wieder was scheinbar unmögliches gibt, nur her damit ;)
 
Zurück
Oben