Frage von MaxMeisterv2, 42

SQL: Gruppieren + Sortieren?

Ich habe eine Tabelle u.a. mit den Spalte nummer und datum Es gibt in der Spalte Nummer mehrfach die die gleiche Nummer (1 bis n mal). Nun möchte ich, dass die Einträge zunächst nach den Nummern gruppiert, danach wird zu jeder Gruppe die neusten Einträge ausgegeben, sortiert absteigend vom Datum Eintrag. Je Gruppierung sollen maximal 5 Einträge zurückgegeben werden.

Antwort
von mastema666, 17

Also wenn ich dich richtig verstehe, dann ist das etwas komplizierter, geht aber durchaus rein via SQL Abfrage, hier recht ausführlich erklärt: https://goo.gl/T1yCGY (oder auch: https://goo.gl/07OprR )

Alternativ, wenn auch sicher nicht optimal und je nach Menge der Datensätze mehr oder weniger ressourcenlastig, könntest du natürlich auch einmal mit "GROUP BY" (oder "DISTINCT") die IDs auslesen und dann in einer Schleife jeweils die 5 neusten mit einem "LIMIT" (sollte man normalerweise nicht machen, SQL-Queries innerhalb von Schleifen sollte man möglichst vermeiden, wenn es nicht allzu viele Daten sind, und die Abfrage ggf auch nicht sonderlich häufig ausgeführt werden soll, auf die Schnelle aber wohl die einfachere Variante).

Kommentar von MaxMeisterv2 ,

http://code.openark.org/blog/mysql/sql-selecting-top-n-records-per-group

Das klingt gut, allerdings fehlt mir dazu das Wissen, um hier noch Anpassungen vorzunehmen.

Könntest Du mir die SQL Anfrage so formulieren, dass am Ende alle Spalten zurückgegegeben werden, welche in der Tabelle x sind?

Erst die Einträge jeweils nach der Spalte nummer in Pakete packen und dann in die Spalte Datum schauen und davon jeweils bis zu 5 Einträge absteigend nehmen.

Danke Dir auf jeden Fall so oder so schon mal!

Kommentar von mastema666 ,

Willst du die Inhalte aller Spalten oder die Namen der Spalten?

Die Inhalte bekommst du über ein einfaches

SELECT * FROM tabelleX

Wenn du die Namen der Spalten willst:

SHOW columns FROM tabelleX

Am einfachsten wäre es wie gesagt, erst die Nummern abzufragen und dann jeweils die 5 neusten Einträge, ganz grob etwa so in der Art: http://pastebin.com/CnbmpCWQ 

Falls es fortlaufende Nummern sind könntest du dir die erste Abfrage btw sogar komplett sparen und einfach alle von X bis Y mit einer "for" Schleife durchgehen.

Antwort
von acdxx, 17

Rein mit SQL ist das ziemlich schwierig. Mir fallen da nur folgende 2 Lösungsansätze ein, welche allerdings beide einen Haken haben:

SELECT * FROM Tabelle ORDER BY Nummer ASC, Datum DESC;

^ Hiermit werden nacheinander für jeden Spieler alle Einträge (absteigend nach Datum sortiert) ausgegeben. Der Haken ist, dass pro Spieler alle Einträge ausgegeben werden und nicht nur die neuesten 5.

SELECT Nummer, SUBSTRING_INDEX(GROUP_CONCAT(Punkte ORDER BY Datum DESC SEPARATOR ', '), ',', 5) as LetzteErgebnisse FROM Tabelle GROUP BY Nummer;

^ Hiermit werden für jeden Spieler die letzten 5 Ergebnisse (Punkte) ausgegeben, aber man sieht das jeweils zugehörige Datum nicht.

Komfortabler wäre es wohl, das mit einer kleinen PHP-Seite zu lösen. Macht sowieso Sinn, denn man will sich die Infos ja nicht immer auf Datenbankebene holen. Die PHP-Seite könnte im ersten Step per SQL alle vorkommenden Spielernummern ermitteln und dann in einer Schleife für jede Spielernummer die neuesten 5 Einträge abrufen. Ist vielleicht nicht die effizienteste Lösung, aber die einfachste.

Kommentar von MaxMeisterv2 ,

Hey Acdxx, erstmal vielen Dank für Deine ausführliche Antwort. Verstehen tue ich davon nicht viel. Habe es jetzt mal ausgeführt, aber die zwei Spalten reichen mir so nicht. Ich brauche den *, also alle Spalten der Tabelle. Da gibts übrigens noch mehr. Mit PHP möchte ich das ungerne machen, weil es ziemlich viele Einträge sind. Hast Du vllt noch ne Idee, wie ich als Ergebnis als Spalten der Tabelle bekomme?

Kommentar von acdxx ,

Ne sry, die SQL-Lösung mit mehr Spalten erschließt sich mir nicht ganz. Ich würde da definitiv auf die einfacherere PHP-Lösung ausweichen - mastema666 hat den nötigen Code ja im Prinzip schon geposted.

Antwort
von Berny96, 29

Was hast du schon probiert und was daran funktioniert nicht?

Meinst du wir helfen dir ohne das du es versuchst?

Kommentar von MaxMeisterv2 ,

Ich kenne mich in SQL so gut wie nicht aus. Daher habe ich auch keine Ansätze weiter geschrieben. Mache das auch nur für unseren Sportverein ehreamtlich :). Wir haben Spielergebnisse, welche ausgegeben werden sollen, aber eben nicht alle, weil das den Rahmen sprengt. Wir wollen pro Spieler immer nur die 5 neusten Einträge bekommen. Vielleicht ist es was mit GROUP BY, aber mehr weiß ich da auch nicht.

Kommentar von wotan38 ,

Das Begrenzen der Ausgabe ist nicht so einfach. Nach Anzahl geht das bei meiner Datenbank überhaupt nicht. Wenn Du die neuesten haben willst, kannst vielleicht auch nach Datum begrenzen, wenn du ein passendes Datum oder sonstige Zeitangabe zur Verfügung hast. Also z.B. nicht die letzten 5 Einträge, sondern die der letzten Woche. Die Datumsrechnerei ist in SQL recht komfortabel, damit kommt man weiter. Man kann z.B. auch den letzten Eintrag und eine weitere zurückliegende Woche ausgeben, wenn man verhindern will, dass zeitlich weiter zurückliegende Einträge ganz herausfallen.

Beispiel für eine solche Bedingung:

WHERE days(datumsfeld) > days(curent date) - 7

würde Einträge der letzten 7 Tage selektieren.

Anmerkung: Die Datenbank speichert ein Kalenderdatum als eine laufende Tages-Nr, beginnend bei 01.01.0001 und endend bei 31.12.9999 nach dem gregorianischen Kalender. Bei der Ein- und Ausgabe wird diese Nummer in ein gültiges Datumsformat und umgekehrt umgewandelt. Das vereinfacht die Sortierung und die Datumsrechnung. 

Keine passende Antwort gefunden?

Fragen Sie die Community