Temporäre Tabelle abfragen?

Hallo,

irgendwie komme ich mit der Abfrage einer temporären Tabelle nicht klar… Ich versuche dies gerade in phpMyAdmin, damit ich es nachher auf mein PHP-Skript übertragen kann.

Hier gebe ich zunächst folgenden SQL-Befehl ein:

CREATE TEMPORARY TABLE temp SELECT id, tid, fid FROM antworten;

Das funktioniert auch soweit, zumindest bringt phpMyAdmin die Meldung:
Ihr SQL-Befehl wurde erfolgreich ausgeführt. (die Abfrage dauerte 0.0026 sek)

Jetzt möchte ich mir gern alle Spalten bzw. Inhalte dieser Tabelle anzeigen lassen. Also gebe ich den SQL-Befehl ein:
SELECT * FROM TEMPORARY TABLE temp

… und bekomme die Fehlermeldung:
FEHLER:

SELECT *
FROM TEMPORARY TABLE temp
LIMIT 0 , 30

MySQL meldet: Dokumentation
#1064 - You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near ‚TABLE temp LIMIT 0, 30‘ at line 1

Mit dem Fehler 1064 in der Dokumentation kann ich nix anfangen:
Error: 1064 SQLSTATE: 42000 (ER_PARSE_ERROR)
Message: %s near ‚%s‘ at line %d

Wenn ich nur abfrage:
select * from temp;
… dann wird mit mitgeteilt, dass diese Tabelle nicht existiert…

Kann mir jemand sagen, wie ich das richtig abfrage?

Grüsse
schuelsche

Ich benutze phpMyAdmin 2.6.2-rc1 und MySQL 4.0.21.

Grüsse
schuelsche

Hallo,

irgendwie komme ich mit der Abfrage einer temporären Tabelle
nicht klar…

mysql\> select \* from foo;
+--------+--------+---------------------+
| wortid | itemid | dt |
+--------+--------+---------------------+
| a | x1 | 0000-00-00 00:00:00 |
| b | x1 | 0000-00-00 00:00:00 |
| a | x2 | 0000-00-00 00:00:00 |
| c | x2 | 0000-00-00 00:00:00 |
| c | x1 | 0000-00-00 00:00:00 |
| d | x3 | 0000-00-00 00:00:00 |
+--------+--------+---------------------+
6 rows in set (0.00 sec)

mysql\> CREATE TEMPORARY TABLE temp SELECT wortid,itemid from foo where wortid select \* from temp;
+--------+--------+
| wortid | itemid |
+--------+--------+
| a | x1 |
| b | x1 |
| a | x2 |
+--------+--------+
3 rows in set (0.00 sec)

mysql\> drop table temp;
Query OK, 0 rows affected (0.00 sec)

kann es sein, dass deine temporäre tabelle mit schliessen des connectes (aka seite aktualisieren im phpmyadmin (php-prozess wird beendet)) gelöscht wird?

Hi,

SELECT *
FROM TEMPORARY TABLE temp
LIMIT 0 , 30

versuchs doch mal mit

SELECT *
FROM temp
LIMIT 0 , 30

den Konstrukt: [SELECT * FROM TEMPORARY TABLE] kenne ich nicht.

Wichtig!
eine temp-Tabelle wird nach Beenden der Verbindung wieder gelöscht.
Deswegen ist sie ja temporär. Sie ist auch nur innerhalb der eigenen Verbindung sichtbar.

HTH
Quaser

Hallo,

kann es sein, dass deine temporäre tabelle mit schliessen des
connectes (aka seite aktualisieren im phpmyadmin (php-prozess
wird beendet)) gelöscht wird?

Ja, irgendwie habe ich diese Vermutung gerade, denn ich habe folgendes festgestellt:

Wenn ich die folgende Abfrage in phpMyAdmin mache, funktioniert das problemlos:

CREATE TEMPORARY TABLE test SELECT a.anid, a.antid, a.anfid, a.antopic, a.anuser, a.ancreated, t.thid, t.thfid, t.thtopic, t.thuser, t.thcreated
FROM antworten a, thread t
WHERE a.anfid = '8'
AND a.antid = t.thid
GROUP BY t.thtopic;

SELECT \*
FROM test
ORDER BY anid DESC 

… in einem SQL-Befehl also.

Wenn ich genau das gleiche in meinem PHP-Skript mache (ich habe es jetzt nur mal aus Übersichtlichkeitsgründen untereinander geschrieben):

$res = mysql\_query("
CREATE TEMPORARY TABLE test SELECT a.anid, a.antid, a.anfid, a.antopic, a.anuser, a.ancreated, t.thid, t.thfid, t.thtopic, t.thuser, t.thcreated 
FROM antworten a, thread t 
WHERE a.anfid = '$fid' 
AND a.antid = t.thid 
GROUP BY t.thtopic; 
select \* from test order by anid desc;
");

while($row = mysql\_fetch\_row($res)) 
{...}

… dann bekomme ich die Fehlermeldung:
Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource in /srv/www/htdocs/test/showthreads.php on line 68.

Demnach existiert die Tabelle nicht mehr unmittelbar, nachdem die Abfrage beendet wurde ($res=…), weil ich sie ja mit while (…$res) ja nicht mehr benutzen kann.

Die connect.inc.php, die für den Zugriff zur Datenbank verwendet wird, ist aktuell nach dem folgenden Prinzip aufgebaut:

<?php //globale Verbindungsdaten<br />$host = "localhost";
$user = "egal";
$pass = "passwort";
$database ="datenbankname";

//Verbindungsaufnahme
$vk = mysql\_pconnect($host, $user, $pass) 
 or die ("Die Verbindung ist fehlgeschlagen!");
 mysql\_select\_db($database, $vk) 
 or die ("keine Datenbankverbindung");
?\>

Muss ich das irgendwie ändern oder wie schaffe ich es in dem PHP-Skript, die Verbindung über die while-Schleife hinweg aufrecht zu erhalten?! Irgendwie kann ich mir das ansonsten nicht erklären, warum die selbe Abfrage in phpMyAdmin funktioniert, aber in meinem Skript nicht…

Auf Hilfe hoffend,
Grüsse
schuelsche

Wenn ich die folgende Abfrage in phpMyAdmin mache,
funktioniert das problemlos:

CREATE TEMPORARY TABLE test SELECT a.anid, a.antid, a.anfid,
a.antopic, a.anuser, a.ancreated, t.thid, t.thfid, t.thtopic,
t.thuser, t.thcreated
FROM antworten a, thread t
WHERE a.anfid = ‚8‘
AND a.antid = t.thid
GROUP BY t.thtopic;

SELECT *
FROM test
ORDER BY anid DESC

… in einem SQL-Befehl also.

dann wuerde ich aber mal das mysql query log konsultieren, was phpmyadmin genau mit welchem connect gemacht hat. der parst schliesslich die statements.

Wenn ich genau das gleiche in meinem PHP-Skript mache (ich
habe es jetzt nur mal aus Übersichtlichkeitsgründen
untereinander geschrieben):

$res = mysql_query("
CREATE TEMPORARY TABLE test SELECT a.anid, a.antid, a.anfid,
a.antopic, a.anuser, a.ancreated, t.thid, t.thfid, t.thtopic,
t.thuser, t.thcreated
FROM antworten a, thread t
WHERE a.anfid = ‚$fid‘
AND a.antid = t.thid
GROUP BY t.thtopic;
select * from test order by anid desc;
");

while($row = mysql_fetch_row($res))
{…}

… dann bekomme ich die Fehlermeldung:
Warning: mysql_fetch_row(): supplied argument is not a valid
MySQL result resource in /srv/www/htdocs/test/showthreads.php
on line 68.

Demnach existiert die Tabelle nicht mehr unmittelbar, nachdem
die Abfrage beendet wurde ($res=…), weil ich sie ja mit
while (…$res) ja nicht mehr benutzen kann.

naja, der schluss ist ein bisschen gewagt, solange du nicht mysql_error() aufrufst und preufst, was dabei rauskommt. in dem zusammenhang erlaube ich mir mal den hinweis, dass es eine gute idee ist die mysql_* funktionen in einen abstraktionslayer zu packen, um eben z.b. fehler und leere ergebnisse behandeln zu koennen, oder ein querylog zu bekommen, wenn man an das servereigene nicht rankommt.

im manual steht im uebrigen eine anmerkung, wonach die statements in mysql_query nicht mit semikolon enden duerfen. und soweit ich mich erinnere (sowas macht man ja auch cniht) sind mehrere statements pro mysql_query() auch verboten. deshalb auch oben der hinweis auf das querylog.

Die connect.inc.php, die für den Zugriff zur Datenbank
verwendet wird, ist aktuell nach dem folgenden Prinzip
aufgebaut:

da ist ein mysql_pconnect drin. wenn du diese include mehrfach in einem script aufmachst, weisst du gar nciht mehr auf welchem handle deine query rauskommt - ganz schlecht fuer deine anwendung. wenn cih mich recht entsinne koennte es sogar sein, dass du das handle mit anderen scripten teilen musst… noch schlechter…

Muss ich das irgendwie ändern oder wie schaffe ich es in dem
PHP-Skript, die Verbindung über die while-Schleife hinweg
aufrecht zu erhalten?!

bleibt sie sowieso. die geht erst weg, wenn du mysql_close() aufrufst, dein script beendeest oder der mysqld weg geht. mit verbindung/handle/whatever ist das ergebnis von mysql_connect gemeint.

Also,
ich glaube ich habe jetzt das Problem gelöst -> allerdings bleibt ein zweites, aber dazu gleich.

Mit folgender Methode kann ich die Tabelle abfragen:

$sql = "CREATE TEMPORARY TABLE test SELECT a.anid, a.antid, a.anfid, a.antopic, a.anuser, a.ancreated, t.thid, t.thfid, t.thtopic, t.thuser, t.thcreated FROM antworten a, thread t WHERE a.anfid = '$fid' AND a.antid = t.thid GROUP BY t.thtopic";
echo mysql\_error();
$res = mysql\_query($sql);
$sql = "select \* from test order by anid desc";
echo mysql\_error();
$res = mysql\_query($sql);
echo mysql\_error();

while($row = mysql\_fetch\_row($res)) 
{}

im manual steht im uebrigen eine anmerkung, wonach die
statements in mysql_query nicht mit semikolon enden duerfen.
und soweit ich mich erinnere (sowas macht man ja auch cniht)
sind mehrere statements pro mysql_query() auch verboten.

Jep, sowas ähnliches wurde mir gerade ausgegeben, als ich „echo mysql_error();“ eingefügt hatte. Also habe ich jetzt die beiden Abfragen nacheinander gestartet - und es geht.

Allerdings passiert nun folgendes:
die Tabelle wird so sortiert ausgegeben, wie ich sie haben möchte. Wenn ich nun aber einen neuen Eintrag mache (also einen neuen Datensatz einfüge), dann rutscht dieser nicht nach oben, so wie es eigentlich sein sollte. In der Datenbank wird vermerkt, dass ein neuer Eintrag vorhanden ist und er wird mir auch in einer anderen Ansicht angezeigt.

Daher nun die Frage, ob bzw. wie lange diese temporäre Tabelle bestehen bleibt.

bleibt sie sowieso. die geht erst weg, wenn du mysql_close()
aufrufst, dein script beendeest oder der mysqld weg geht. mit
verbindung/handle/whatever ist das ergebnis von mysql_connect
gemeint.

Was heisst „mein Skript beende“? Ich rufe zwischenzeitlich ein anderes Skript über eine URL auf und trotzdem ändert sich die Anzeige nicht, auch wenn das Skript mit der temporären Tabelle neu geladen wird.
Setze ich dann einfach ein
mysql_close()
hinter die while-Schleife?!
Im Prinzip muss die temporäre Tabelle neu eingelesen werden. Oder kann ich die irgendwie „zwangslöschen“?

Grüsse
schuelsche

Tja, vermutlich liegt der Fehler eher in meiner Abfrage. Ich dachte eigentlich, dass ich alle Daten, die ich haben will, in einer bestimmten Reihenfolge in einer temporären Tabelle speichern kann, in dem Fall sortiert nach der höchsten „anid“.

Wenn ich dann den zweiten Befehl starte und mir die temporäre Tabelle nach „thtopic“ sortiert anzeigen lassen will, dann werden mir zwar richtig die Topics gruppiert angezeigt - also die doppelten weggelassen - aber die Reihenfolge der Antworten stimmt dann nicht mehr.

Wie kann ich denn die temporäre Tabelle gleichzeitig nach zwei Kritieren abfragen lassen?! Ich möchte thtopic gruppiert, aber gleichzeitig in der Abfrage die höchste anid angezeigt bekommen.

(Hintergrund ist ein Forum, bei dem ich den Threadtitel, den Threadersteller, das Erstelldatum, den Verfasser der letzten Antwort und das Datum der letzten Antwort anzeigen lassen will. Natürlich soll immer der Thread ganz oben stehen, der die neueste Antwort hat.)

Grüsse
schuelsche

Daher nun die Frage, ob bzw. wie lange diese temporäre Tabelle
bestehen bleibt.

bleibt sie sowieso. die geht erst weg, wenn du mysql_close()
aufrufst, dein script beendeest oder der mysqld weg geht. mit
verbindung/handle/whatever ist das ergebnis von mysql_connect
gemeint.

Was heisst „mein Skript beende“?

naja, exit oder ende des scriptes aber wie gesagt, deine pconnect mögen da sideeffects ausloesen…

Ich rufe zwischenzeitlich ein
anderes Skript über eine URL auf und trotzdem ändert sich die
Anzeige nicht, auch wenn das Skript mit der temporären Tabelle
neu geladen wird.

das konstrukt kann ich mir im moment nivht vorstellen, kannst du das irgendwie beschrieben?

wenn es so sein sollte:
start script a
create temp
starte script b
select from temp
beende script b
beende script a

dann kann script b in temp lesen, weil die connection von script a noch auf ist.

Setze ich dann einfach ein
mysql_close()
hinter die while-Schleife?!

keine ahnung, ich weiss ncoh cnith was du erreichen willst.

Im Prinzip muss die temporäre Tabelle neu eingelesen werden.

was meinst du mit neu einlesen

Oder kann ich die irgendwie „zwangslöschen“?

drop table

habe ich schon bemerkt, das ich denke, dass du mit deinem ansatz über die temporäre tabelle auf dem holzweg bist?

Tja, vermutlich liegt der Fehler eher in meiner Abfrage. Ich
dachte eigentlich, dass ich alle Daten, die ich haben will, in
einer bestimmten Reihenfolge in einer temporären Tabelle
speichern kann, in dem Fall sortiert nach der höchsten „anid“.

die originäre reihenfolge in einer tabelle ist immer als zufällig zu betrachten!

Wie kann ich denn die temporäre Tabelle gleichzeitig nach zwei
Kritieren abfragen lassen?!

auf abfrageebene sollten sich afaik temporäre von anderen tables nciht unterscheiden

Ich möchte thtopic gruppiert, aber
gleichzeitig in der Abfrage die höchste anid angezeigt
bekommen.

select max(anid) ,thtopic from foo group by thtopic ?

keine ahnung. schick mal die sql-struktur

Also,
grundsätzlich möchte ich folgendes realsieren:

Ich möchte eine Tabelle darstellen, die folgenden Inhalt anzeigt:

Titel | Autor | Datum | letzter Beitrag | Datum
---------|---------|-----------|-----------------|-------
thopic | thuser | thcreated | anuser | ancreated
thread | thread | thread | antworten | antworten

Und zwar soll diese Tabelle jeweils den Thread ganz oben anzeigen, auf den die neueste Antwort gegeben wird, also quasi nach Thread gruppiert und nach neuester Antwort sortiert.

Folgende drei Tabellen bilden die Grundlage für meine Abfrage:

foren
foid | foname | foinhalt
-------|--------|--------
int(11)|tinytext|text

thread
thid | thfid | thtopic | thuser | thcreated
-------|-------|---------|------------|----------
int(11)|int(11)|tinytext |varchar(100)|datetime

antworten
anid | antid | anfid | anuser | antopic | antext | ancreated
-------|-------|-------|--------|---------|--------|-----------
int(11)|int(11)|int(11)|tinytext|tinytext |text |datetime

Die jeweilige …id wird automatisch hochgezählt, das jeweilige …created wird durch ein create(now) in der Datenbank erzeugt. Die neuste Antwort/Thread bekommt automatisch auch die höchste ID (man könnte also sowohl nach an/thcreated wie auch nach an/thid abfragen).

Meine Abfrage, um die obige Tabelle darzustellen war die folgende:

select a.anid, a.antid, a.anfid, a.anuser, a.ancreated, t.thid, t.thtopic, t.thuser, t.thcreated
from antworten a, thread t
where a.anfid=$fid and a.antid=t.thid
order by a.anid desc

… wobei $fid durch den Link übergeben wird.

Das ganze soll letztendlich ein Forum werden, wo in dieser Threadübersicht der Thread als erstes angezeigt werden soll, der die letzte Antwort erhalten hat.
Leider wird mir bei obiger Abfrage zwar die Threads nach Antwort sortiert, aber der Threadtitel wird immer wiederholt. Sieht dann etwa so aus:

Titel | Autor | Datum | letzter Beitrag | Datum
-----------|---------|-----------|-----------------|-------
Testtitel | user1 | 01.01.05 | user25 | 02.02.05
Testtitel | user1 | 01.01.05 | user99 | 28.01.05
Neuer Test | user99 | 28.01.05 | user51 | 25.01.05
Testtitel | user1 | 01.01.05 | user51 | 24.01.05

Wie kann ich jetzt die Abfrage über die beiden Tabellen so gestalten, dass die doppelten „Testtitel“ nicht angezeigt werden?! Mit Distinct kann man irgendwie wohl nur ein Argument überprüfen und nicht eins von 9, wie ich es hier tue…

Quasi „zeige immer den neuesten Beitrag zuerst an“… Das dachte ich durch eine virtuelle Tabelle ermöglichen zu können, funktioniert ja aber auch nicht. Das Problem ist einfach, dass ich zwei Tabellen nach zwei Kriterien sortieren will (eines gruppieren und eines sortieren…

select max(anid) ,thtopic from foo group by thtopic ?

… das werde ich mal testen. Allerdings habe ich die Vermutung, dass mir hier dann nur die max(anid) angezeigt wird und nicht der Rest, den ich aus der Tabelle antworten brauche…

Grüsse
schuelsche

Also,
grundsätzlich möchte ich folgendes realsieren:

Ich möchte eine Tabelle darstellen, die folgenden Inhalt
anzeigt:

Titel Autor Datum letzter Beitrag Datum
thopic thuser thcreated anuser ancreated
thread thread thread antworten antworten

Und zwar soll diese Tabelle jeweils den Thread ganz oben
anzeigen, auf den die neueste Antwort gegeben wird, also quasi
nach Thread gruppiert und nach neuester Antwort sortiert.

Folgende drei Tabellen bilden die Grundlage für meine Abfrage:

foren

foid foname foinhalt
int(11) tinytext text

thread

thid thfid thtopic thuser thcreated
int(11) int(11) tinytext varchar(100) datetime

antworten

anid antid anfid anuser antopic antext ancreated
int(11) int(11) int(11) tinytext tinytext text datetime

Die jeweilige …id wird automatisch hochgezählt, das jeweilige
…created wird durch ein create(now) in der Datenbank erzeugt.
Die neuste Antwort/Thread bekommt automatisch auch die höchste
ID (man könnte also sowohl nach an/thcreated wie auch nach
an/thid abfragen).

Meine Abfrage, um die obige Tabelle darzustellen war die
folgende:

select a.anid, a.antid, a.anfid, a.anuser, a.ancreated,
t.thid, t.thtopic, t.thuser, t.thcreated
from antworten a, thread t
where a.anfid=$fid and a.antid=t.thid
order by a.anid desc

… wobei $fid durch den Link übergeben wird.

Das ganze soll letztendlich ein Forum werden, wo in dieser
Threadübersicht der Thread als erstes angezeigt werden soll,
der die letzte Antwort erhalten hat.
Leider wird mir bei obiger Abfrage zwar die Threads nach
Antwort sortiert, aber der Threadtitel wird immer wiederholt.
Sieht dann etwa so aus:

Titel Autor Datum letzter Beitrag Datum
Testtitel user1 01.01.05 user25 02.02.05
Testtitel user1 01.01.05 user99 28.01.05
Neuer Test user99 28.01.05 user51 25.01.05
Testtitel user1 01.01.05 user51 24.01.05

Wie kann ich jetzt die Abfrage über die beiden Tabellen so
gestalten, dass die doppelten „Testtitel“ nicht angezeigt
werden?!

select a.anid, a.antid, a.anfid, a.anuser, a.ancreated,
t.thid, t.thtopic, t.thuser, t.thcreated
from antworten a, thread t
where a.anfid=$fid and a.antid=t.thid
group by a.antid
order by a.ancreated desc

select max(anid) ,thtopic from foo group by thtopic ?

… das werde ich mal testen. Allerdings habe ich die
Vermutung, dass mir hier dann nur die max(anid) angezeigt wird
und nicht der Rest, den ich aus der Tabelle antworten
brauche…

schau was group by macht:

mysql\> select \* from foo;
+--------+--------+---------------------+
| wortid | itemid | dt |
+--------+--------+---------------------+
| a | x1 | 0000-00-00 00:00:00 |
| b | x1 | 0000-00-00 00:00:00 |
| a | x2 | 0000-00-00 00:00:00 |
| c | x2 | 0000-00-00 00:00:00 |
| c | x1 | 0000-00-00 00:00:00 |
| d | x3 | 0000-00-00 00:00:00 |
+--------+--------+---------------------+
6 rows in set (0.01 sec)

mysql\> select max(wortid),itemid from foo group by itemid;
+-------------+--------+
| max(wortid) | itemid |
+-------------+--------+
| c | x1 |
| c | x2 |
| d | x3 |
+-------------+--------+
3 rows in set (0.13 sec)

mysql\>

Hallo,

select a.anid, a.antid, a.anfid, a.anuser, a.ancreated,
t.thid, t.thtopic, t.thuser, t.thcreated
from antworten a, thread t
where a.anfid=$fid and a.antid=t.thid
group by a.antid
order by a.ancreated desc

Die Abfrage habe ich auch schon durch, aber ich haben den Eindruck, dass dabei die letzte Abfrage „order by…“ dann überhaupt nicht mehr interessiert, weil mir dann zwar die Threads nach Artikel sortiert angezeigt werden, allerdings mit irgendeiner Antwort (nicht der letzten) und die Threads werden in alphabetischer Reihenfolge sortiert. Die Reihenfolge … order by a.ancreated desc group by a.antid… ergibt eine Fehlermeldung…

Aber da fällt mir gerade was auf:
bisher war meine Abfrage immer so:

group by t.thtopic
order by a.anid desc

Kann es sein, dass das deshalb nicht funktioniert, weil ich zwei verschiedene Tabellen auf die Art und Weise abfrage? Weil in Deinem obigen Beispiel fragst Du ja nur die eine Tabelle antworten ab:

group by a.antid
order by a.ancreated desc

Für mich ist das echt ein Rätsel. Klar könnte ich die ancreated und den anuser auch in die Tabelle thread eintragen lassen, aber das ist doch eine unnötige Redundanz, die ich eigentlich vermeiden möchte.

Grüsse
schuelsche

Hallo,

dank dog.je konnte ich das Problem nun lösen. Die Abfrage, um die gewünschte Ansicht zu erhalten lautet korrekt:

$sql = "select ";
$sql .= "a.anid, a.antid, a.anfid, a.anuser, max(a.ancreated) as **foo**";
$sql .= " , t.thid, t.thfid, t.thtopic, t.thuser, t.thcreated ";
$sql .= " from antworten a, thread t ";
$sql .= " where a.anfid='$fid' and a.antid=t.thid ";
$sql .= " and a.anfid='$fid' and a.antid=t.thid ";
$sql .= " GROUP BY t.thtopic ";
$sql .= " order by **foo** desc";

$res = mysql\_query("$sql");

Vielen Dank für die Hilfe,

Grüsse
schuelsche