2012-03-29 6 views
5

Ich brauche eine MySql-Anweisung, die alle Zeilen auswählt, sowie wie viele Gesamtzeilen es gibt.MySql Auswahl der Anzahl der Zeilen als zusätzliche Spalte?

Ich war mit

mysql_query("SELECT * FROM posts LIMIT 0, 5"); 

... versuchen, die Zählung hinzuzufügen:

mysql_query("SELECT *, COUNT(*) AS total FROM posts LIMIT 0, 5"); 

... aber das gibt nur eine einzige Zeile.

Auch, wenn es eine bessere Möglichkeit gibt, die Summe als eine zusätzliche Spalte zu jeder Zeile hinzufügen, dann würde ich stattdessen möchten. Vielen Dank!

+2

Wenn Sie PHP verwenden, warum nicht 'mysql_num_rows' – hjpotter92

+1

@ hjpotter92 verwenden, aber es hängt davon ab, welche" totale "OP denkt. Summe aktuell ausgewählt (als "mysql_num_rows" ist in Ordnung) oder Anzahl der Zeilen in der gesamten Tabelle. –

+0

Guter Punkt, @Michal. Ich habe beide Fälle in meiner Antwort angesprochen. –

Antwort

9

Ich brauche eine MySql-Anweisung, die alle Zeilen auswählt, sowie wie viele insgesamt Reihen gibt.

Wenn wörtlich genommen, ist dies nicht möglich. Das Ergebnis einer SQL-Abfrage ist eine (virtuelle) Tabelle. Die Spalte in jeder Zeile in dieser Ergebnistabelle liefert einen Wert, der nur dieser Zeile zugeordnet ist, und die Zeilen sind voneinander unabhängig.

Es gibt viele Möglichkeiten, die rowcount des gesamten Ergebnisses zu erfassen, aber es ist entweder in zwei Anweisungen oder mit einer Abfrage, die konzeptionell anders als das, was Sie haben, getan. (Lösungen unten)

Es gibt einen Aspekt in Ihrer ursprünglichen Frage, die auf vielfältige Weise interpretiert werden könnte:

sowie wie viele insgesamt Reihen gibt es

Dies entweder bedeuten könnte:

  1. Zählen Sie jede zurückgegebene Zeile im Ergebnis.
  2. jede Zeile Count, die zurückgegeben worden wäre, wenn es nicht für die LIMIT-Klausel (die das Ergebnis auf 5 Reihen in diesem Fall kürzt) war

(I sowohl unten mit Antworten kommen werde)

aber das gibt nur eine einzelne Zeile zurück. Ich vermute, es ist, weil COUNT (*) für jede Zeile gleich ist, und aus irgendeinem Grund gibt MySql nur Zeilen mit eindeutigen Werten dafür zurück? Ich habe keine Ahnung.

COUNT ist eine Aggregatfunktion. Wenn Sie eine Aggregatfunktion verwenden, bitten Sie die Datenbank, Gruppen von Zeilen zusammenzufassen und einige Aspekte davon in eine einzelne Zeile zu projizieren. Was ist verwirrend ist, dass mysql auch Sie nicht-Aggregat und Aggregat Ausdrücke in der gleichen SELECT Liste mischen. Die meisten anderen Datenbanken erlauben dies nicht und geben Ihnen einen Fehler, aber leider nicht MySQL.

Aber COUNT (*) nicht aggregiert jedoch immer noch alle Zeilen in eine einzige Zeile, die die gesamte Gruppe von Zeilen darstellt.

Auch wenn es eine bessere Möglichkeit gibt, die Summe als eine zusätzliche Spalte zu jeder Zeile hinzufügen, dann würde ich stattdessen möchten. Vielen Dank!

Ja, es gibt mehrere Möglichkeiten.

Wenn Sie die Anzahl der Zeilen bekommen zurückgegeben PHP, so, nachdem MySQL seine limit-Klausel angewendet wird, schlage ich vor, die PHP-Funktion mysql_num_rows (http://www.php.net/manual/en/function.mysql-num-rows.php) nachdem ich die mysql_query Anruf einfach anrufen.

Wenn Sie die Anzahl der Zeilen erhalten möchten, die in Abwesenheit der LIMIT-Klausel zurückgegeben wurden, empfehle ich es in zwei Schritten durchzuführen: Führen Sie zunächst eine leicht modifizierte Version Ihrer ursprünglichen Abfrage und dann sofort danach aus das, rufen Sie die FOUND_ROWS Funktion von MySQL. (Siehe http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_found-rows)

Es würde wie folgt aussehen:

$result = mysql_query('SELECT SQL_CALC_FOUND_ROWS * FROM posts LIMIT 0, 5'); 
//do stuff with the result, but don't do any other queries 

//get the total number of rows (disregarding the LIMIT clause) 
$result = mysql_query('SELECT FOUND_ROWS()'); 

Die SQL_CALC_FOUND_ROWS Modifikator MySQL Spur der Gesamtzahl der Zeilen zu halten, sagt vor der LIMIT Klausel anzuwenden und FOUND_ROWS() kehrt diese Zahl. Halten Sie 2 Dinge beachten:

  1. beide mysql_query Anrufe über die gleiche Verbindung ausgeführt werden soll
  2. Sie eine weitere Abfrage dazwischen diese Anrufe zu mysql_query

Oh, letzte Bemerkung nicht ausgeführt werden: bei der Verwendung von LIMIT, möchten Sie in der Regel die Ergebnisse in einer bestimmten Weise bestellt werden. Normalerweise verwenden Leute LIMIT für Seitenumbruch. Wenn Sie nicht die Zeilen bestellen, ist die Reihenfolge unbestimmt und nachfolgende Abfragen von früheren Aussagen zurückgeben, zurückgegebenen Zeilen bereits selbst wenn der Offset LIMIT unterscheidet. Sie können explizit das Ergebnis bestellen, indem eine ORDER BY-Klausel. (http://dev.mysql.com/doc/refman/5.5/en/select.html)

+0

Ja, ich stimme Ihnen ganz zu Ihrer letzten Aussage zu, es ist in der Tat möglich, die Ergebnismenge explizit mit einer 'ORDER BY'-Klausel anzuordnen. Tatsächlich würde ich sogar so weit gehen zu sagen "** nur", indem ich eine 'ORDER BY'-Klausel verwende. ;) Nur etwas sarkastisch, tut mir leid. Ich finde deine Antwort gut ausgearbeitet und erziehend, +1. –

+1

+1 für 'FOUND_ROWS()' –

+0

@Andrriy heh, danke :) Nur ein Nitpick, aber in MySQL, zum Guten oder zum Schlechten, eine GROUP BY-Klausel ist auch garantiert, eine geordnete Ergebnismenge zurückgeben. Sie können ASC- und DESC-Modifikatoren sogar für die Ausdrücke in der GROUP BY-Liste angeben. –

8

Ich bin mir nicht sicher, an welcher Summe Sie denken: Summe aktuell ausgewählte oder Anzahl aller Zeilen in der ganzen Tabelle. Dies gibt Nummern aller Zeilen in ganzen Tisch, natürlich in jeder Zeile denselben Wert:

mysql_query("SELECT *, (select COUNT(*) from posts) AS total FROM posts LIMIT 0, 5"); 
+0

Okay, danke, das ist perfekt. Ich nehme an, ich könnte nur diese andere Abfrage ändern, um die Anzahl der gewünschten Werte auszuwählen. Ist das furchtbar ineffizient? Werden doppelt so viele Anfragen gestellt? – mowwwalker

+0

@Walkerneo Wenn das Ihre eigentliche Frage ist, dann ist mysql_num_rows die beste Lösung. – hjpotter92

+0

@Walkerneo es ist nicht korreliert (es gibt keine Korrelation zwischen äußeren und inneren Abfrage), so sollte es nicht an Effizienz verlieren. Und ja, Sie können die innere Abfrage auf alles beschränken, was Sie wollen. –

1

Ich glaube, Sie werden dieses Problem zu verkomplizieren. Ich sehe kein Problem mit zwei Abfragen.

erste Abfrage aller Beiträge zu bekommen (ich nehme an, Sie die Summe in der gesamten Tabelle wollen):

SELECT COUNT(*) AS total FROM posts; 

und eine zweite, für Ihre Beiträge zur Abfrage:

SELECT * FROM posts LIMIT 0, 5 

Die Grund ist, dass es nicht immer schlecht ist, Daten mit mehr als einer Abfrage abzufragen, besonders wenn es sinnvoll ist.

Wenn Sie es als zusätzliche Spalte mit say eine Unterabfrage hinzufügen würden, hätten Sie die Summe in jeder Zeile, aber Sie würden immer noch zwei Abfragen ausführen (oder würde die Unterabfrage für jede Zeile ausgeführt werden, I kann mich nicht erinnern?)

Es ist auch mehr Flexibilität bietet die Zählung zuerst zu erhalten, da einige Abfragen die falsche Gesamtanzahl je nach zurückkehren wird, wie komplex Ihre Abfrage.Und möglicherweise müssen Sie die Anzahl-Abfrage ändern, damit Sie die richtige Summe erhalten und richtig paginieren können.

Zum Beispiel im Fall einer Eins-zu-viele-Abfrage, sagen Sie möchten Posts und Kommentare erhalten, würden Sie die falsche Anzahl erhalten, da der Post für jeden Kommentar für diesen Beitrag dupliziert werden würde.

Verkürzte Beispiel:

post_id | comment_id 
1  | 1 
1  | 2 
2  | 3 
3  | 4 
3  | 5 

So machen Sie es richtig würden Sie zuerst die folgende Abfrage ausführen müssen Beiträge erhalten:

SELECT COUNT(*) AS total FROM posts; 

Und dann würden Sie ausführen müssen:

SELECT id FROM posts limit 0, 5; 

Und schließlich würden Sie laufen:

select p.id, c.id from posts p left join comments c on c.post_id = p.id where id in(id list from above query) 

Offensichtlich würde Ihre Abfrage nicht in das obige Problem laufen. Aber ich versuche nur zu veranschaulichen, warum es gut sein kann, die Gesamtanzahl in einer separaten Abfrage zu erhalten.

+1

Die Verwendung mehrerer Abfragen erfordert jedoch Überlegungen über Parallelität. Was passiert, wenn nach der ersten Abfrage, aber vor dem Start der zweiten Abfrage Zeilen hinzugefügt oder entfernt werden? Die von der zweiten Abfrage zurückgegebene Zählung würde nicht mit den Ergebnissen der ersten übereinstimmen.(Sie können dies vermeiden, indem Sie beide Abfragen in einer einzelnen Transaktion mit einer ausreichend hohen Isolationsstufe ausführen.) – Wyzard

+0

Ja, Sie sollten die Abfragen in einer Transaktion ausführen. – Gohn67

Verwandte Themen