Select fuer Paging?
am 05.11.2004 10:31:55 von Oliver Berse
Hallo NG,
ich moechte das Ergebnis eines recht komplexen Selects aus mehreren
MySQL-Tabellen als HTML-Tabelle darstellen. Dabei soll der User die
Moeglichkeit haben durch die Datensaetze zu blaettern und sich immer nur n
Zeilen anzeigen zu lassen. Dafür hänge ich an das Select ein Limit
StartZeile,AnzahlZeilen. Mit PHP berechne ich dann aus der Gesamtzahl der
Datensaetze die Anzahl der Seiten und generiere die Navigationslinks mit
veraendertem Startwert. Das funktioniert soweit auch alles und sieht etwa so
aus:
Seite: [1] [2] [3]
Felder von Datensatz StartZeile
Felder von Datensatz StartZeile+1
usw.
Problem: Fuer die Berechnung der Anzahl der Navigationslinks brauche ich die
Gesamtzahl aller vom Select gelieferten Zeilen, fuer die Ausgabe nur die mit
Limit bestimmte Menge. D.h.ich muss mein automatisch generiertes und langes
Select bei jeder Ausgabe immer zweimal ausführen, was mir etwas
Performance-Sorgen macht. Die Navigation sollte auch bei >100.000 Zeilen
noch ohne Verzoegerung laufen.
Kennt also jemand eine Moeglichkeit, die Abfrage aller Datensaetze fuer das
Paging zu umgehen und trotzdem die Zahl der Navigationslinks/Seiten zu
berechnen? Vielleicht koennte ich das Select ueber alle Zeilen nur einmal
ausfuehren und die Gesamtzahl zwischenspeichern, waere beim ersten
Seitenaufruf aber imer noch eine Totalauswahl. Das Select fuer die
Ermittlung der Gesamtzahl laesst sich leider auch nicht auf weniger Felder
reduzieren.
mfG,
Oliver
Re: Select fuer Paging?
am 05.11.2004 12:42:15 von Michael Rittweger
Hallo, Oliver!
> Kennt also jemand eine Moeglichkeit, die Abfrage aller Datensaetze fuer
> das
> Paging zu umgehen und trotzdem die Zahl der Navigationslinks/Seiten zu
> berechnen?
Ich hab mir vor einiger Zeit auch so eine Navigation zusammengebastelt. Auch
dort stand ich vor dem Problem, einerseits einen recht umfangreichen Filter
in der WHERE-Klausel zu haben, andererseits aber wissen zu müssen, welche
Seiten aktuell dargestellt wird und wieviele Seiten es insgesamt gibt.
Ich sah auch keine andere Möglichkeit, als pro Seite 2 Queries nacheinander
abzuschicken. Etwa so in der Art:
SELECT count($idfeld) FROM $tabelle WHERE ($filter);
--> Damit hast Du die Gesamtzahl der Datensätze, die durch den Filter
passen.
Und dann eben das eigentliche:
SELECT $feldnamen FROM $tabelle WHERE ($filter) ORDER BY $sortierung LIMIT
$start,$anzahl;
--> Damit hast Du dann die Zeilen für die aktuelle Seite.
> Vielleicht koennte ich das Select ueber alle Zeilen nur einmal
> ausfuehren und die Gesamtzahl zwischenspeichern,
Das hatte ich auch zuerst überlegt. Aber: Während der eine Besucher
blättert, könnte ein anderer Besucher einen neuen Datensatz einfügen oder
löschen. Damit würde Deine Navigation dann etwas ins Schleudern kommen, weil
die Gesamtzahl nicht mehr stimmt.
> waere beim ersten
> Seitenaufruf aber imer noch eine Totalauswahl. Das Select fuer die
> Ermittlung der Gesamtzahl laesst sich leider auch nicht auf weniger
> Felder
> reduzieren.
Naja, mein erster Ansatz damals war auch ein
SELECT $idfeld FROM $tabelle WHERE ($filter);
Danach hab ich dann geguckt, wieviele Datensätze daraus resultieren. Mit
einem count() dürfte das aber eine Ecke performanter sein, schätze ich mal.
An den hatte ich zuerst nur ganz einfach nicht gedacht, schlichtweg
vergessen.
Ein SELECT * ... ist aber in jedem Fall nicht notwendig, um die Anzahl der
Datensätze herauszufinden. Das PrimaryKEy-Feld sollte völlig reichen.
> Oliver
Gruß, Michael
Re: Select fuer Paging?
am 06.11.2004 01:55:59 von Matthias Esken
Michael Rittweger schrieb:
>> Kennt also jemand eine Moeglichkeit, die Abfrage aller Datensaetze fuer
>> das
>> Paging zu umgehen und trotzdem die Zahl der Navigationslinks/Seiten zu
>> berechnen?
>
> Ich hab mir vor einiger Zeit auch so eine Navigation zusammengebastelt. Auch
> dort stand ich vor dem Problem, einerseits einen recht umfangreichen Filter
> in der WHERE-Klausel zu haben, andererseits aber wissen zu müssen, welche
> Seiten aktuell dargestellt wird und wieviele Seiten es insgesamt gibt.
>
> Ich sah auch keine andere Möglichkeit, als pro Seite 2 Queries nacheinander
> abzuschicken. Etwa so in der Art:
>
> SELECT count($idfeld) FROM $tabelle WHERE ($filter);
Aus der MySQL-Dokumentation:
| mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
| WHERE id > 100 LIMIT 10;
| mysql> SELECT FOUND_ROWS();
Für Details bitte ich darum die Doku selber zu konsultieren.
Gruß,
Matthias
Re: Select fuer Paging?
am 06.11.2004 11:37:57 von Michael Rittweger
Hallo, Mathias!
> | mysql> SELECT SQL_CALC_FOUND_ROWS
> Für Details bitte ich darum die Doku selber zu konsultieren.
Hm, über das Ding bin ich mal flüchtig vor einiger Zeit gestolpert. Da ich
aber "MySQL 3.23.55-Max-log" bei all-inkl.com verwende und das erst ab 4.0.0
verfügbar ist, hab ich es nicht weiter verfolgt und erstmal 'ad acta'
gelegt. Aber jetzt, wo Du daran erinnerst...
Wenn man die passende MySql-Version hat, ist es wirklich genau das, was man
braucht. Die Beschreibung zu FOUND_ROWS() geht ja sogar explizit auf
"paging" ein.
Es klingt aber auch ein wenig MySql-spezifisch, weswegen ich es auch nur
ungern benutzt hätte. Oder ist das in einem allgemeineren SQL-Standard? In
MS-Access 97 und Borland-InterBase 5 kannte ich das vorher noch nicht.
> Matthias
Gruß, Michael
Re: Select fuer Paging?
am 06.11.2004 13:22:28 von Matthias Esken
Michael Rittweger schrieb:
>> | mysql> SELECT SQL_CALC_FOUND_ROWS
>> Für Details bitte ich darum die Doku selber zu konsultieren.
>
> Es klingt aber auch ein wenig MySql-spezifisch, weswegen ich es auch nur
> ungern benutzt hätte. Oder ist das in einem allgemeineren SQL-Standard?
Das ist ausschließlich in MySQL verfügbar. Gleiches gilt auch für die
LIMIT-Syntax.
Gruß,
Matthias