SQL Datensätze filtern (Max / Group by)

netcon

Newbie
Registriert
Mai 2007
Beiträge
5
Hallo Zusammen
Ich kenne mich in SQL nur mit den Basics aus und stehe nun bei einem Problem an. Ich möchte eine Abfrage aus einer MySQL DB machen, bei der nur jeweils die Zeilen mit der höchsten Versions-Nummer ausgegeben werden,

Man hat z.B. folgende Tabelle:
________________________
| id | Version | Text |
=====================
| 1 | 1 | row1 |
| 1 | 2 | row2 |
| 2 | 1 | row3 |
---------------------------

In meiner Ausgabe will ich nun nur die Datensätze mit der höchsten Version-Nummer haben. Also z.B:

| 1 | 2 | row2 |
| 2 | 1 | row3 |

Wenn ich nun folgende Abfgrage verwende:
SELECT id, max(version), text FROM `test` Group by id

bekomme ich folgendes Ergebnis.
| 1 | 2 | row1 |
| 2 | 1 | row3 |

Ich bekomme also nur die grösste Version-Nummer für die jeweilige ID zurück, aber nicht die ganze Zeile, die zu der ID gehört. Die Spalte Text gehört immer noch zum ersten Datensatz.

Müsste man hier die Abfrage mit einer zweiten Select Anweisung in einer Where-Abfrage machen oder etwas in der Art?

Vielen Dank für eure Hilfe.
 
Danke für die Antwort.

Group by verwende ich bereits. Leider bekomme ich damit jedoch nicht mein gewünschtes Ergebnis.
Die Tabelle hat die beiden Primary Keys id und version.
Ich möchte nun für jede einzelne id nur die angezeigt bekommen, welche die grösse Versions-Nummer hat.
Ich habe bereits Kombinationen mit Order By und Group By versucht, jedoch klappte dies auch nicht. Irgendwie denke ich, dass ich mit Group by hier nicht weiter kommen kann?
 
So sollte das funktionieren:
Code:
SELECT * FROM (SELECT id, version, text
  FROM testtbl AS t
  ORDER BY id ASC, version DESC) AS tbl
  GROUP BY id
Die geschachtelte Abfrage deswegen, weil in der korrekten Syntax das GROUP BY vor dem ORDER BY kommen muss, in diesem Fall aber sortiert werden soll, bevor das GROUP BY greift.
 
Und so wird es funktionieren :p

Dies geht nur falls die höchste Version auch dem jeweils hösten Wert der Spalte Text zugeordnet ist.
Code:
SELECT id, MAX(version), MAX(text)
FROM test
Group by id

Hiermit bist du auf der sicheren Seite
Code:
SELECT  test.id, test.version, test.text
  FROM test
  INNER JOIN ( SELECT  id, MAX(version) max_version
	          FROM test
	          Group by id
              ) AS max_Vers_je_Id
	ON test.id = max_Vers_je_Id.id
	AND test.version = max_Vers_je_Id.max_version
order by id, version
 
Zuletzt bearbeitet:
Vielen Dank für die Abfrage und die Beschreibung des Syntax.
Funtkioniert super! :)
 
deine anforderung ist ein bisschen weird.. wenn du in deiner gruppe z.b. zwei oder mehr zeilen mit version=2 hast, welchen wert text willst du dann genau wählen? die MAX funktion ist ja nicht da um den größten datensatz zu suchen, sondern nur den größten wert (einer einzelnen spalte).
 
Ich weiss dass ich mich wohl ein wenig zu ungenau ausgedrück habe, weiss aber auch nicht genau wie ichs mache soll :)

Die Lösung von Cobinja ist eigentlich das, was ich gesucht habe. Mit Max() funktioniert es nicht, da hast du recht.

Was ich noch vergessen zu sagen habe ist, dass id und Version zusammen den Primary Key bilden. Es wird also nie eine id geben, die zweimal die selbe Version hat.

Mein Problem bestand darin, dass ich zwar Group By verwendete, dann jedoch die grösste Versions-Nummer mit Max() herausfinden wollte.
Cobinja löste das Problem, indem zuerst die Datensätze korrekt soritert werden:
Die geschachtelte Abfrage deswegen, weil in der korrekten Syntax das GROUP BY vor dem ORDER BY kommen muss, in diesem Fall aber sortiert werden soll, bevor das GROUP BY greift.

Auf diese Weise liefert mir Group By das gewünschte Ergebnis.

Nochmals vielen Dank für die Antworten!
 
Hallo netcon,

du schreibst das es nicht mit MAX() funktioniert.
Ist dies auch mit meinen SQL-Statement so?
Kann dies leider nicht testen, weil kein MySQL installiert ist.

Das MySQL so lässig mit der Syntax umgeht und nicht alle verwendete Attribute entweder im Group By oder Aggregat stehen müssen (wie im Befehl von Cobinja), verwundert (schockiert) mich schon ein wenig.
 
Zuletzt bearbeitet:
Hallo knoxyz

Also folgendes Statemant bringt nicht den erwünschten Effekt:
Code:
SELECT id, MAX(version), MAX(text)
FROM test
Group by id

Wenn ich z.B. folgende Daten haben:
| id | Version | Text |
=====================
| 1 | 1 | row1 |
| 1 | 2 | row0 |
| 2 | 1 | row3 |
---------------------------

dann bekomme ich folgendes zurück:
| 1 | 2 | row1 |
| 2 | 1 | row3 |

row1 gehört jedoch zum ersten Datensatz und nicht zum zweiten. Es ist einfach der höhere Wert in der Spalte.
richtig würde sein:
| 1 | 2 | row0 |
| 2 | 1 | row3 |


Dein 2. Query liefert jedoch das korrekte Ergebnis.
Da ich die Abfrage jedoch etwa 10 mal immer in leicht abgeänderter Form verwenden musste, benutze ich die Abfrage von Cobinja, da es mir leichter fiehl, die Abfrage abzuändern.
 
ist auch klar das die kurz version nicht funktioniert
aber die langversion sollte funtionieren das order by nach version
könntest du streichn da es kein sinmacht
das "inner" vor join ist auch unnötig.
Code:
SELECT  a.id, a.version, a.text
  FROM test as a
  JOIN ( SELECT  id, MAX(version) max_version
	          FROM test
	          Group by id
              ) AS b
	ON a.id = b.id
	AND a.version = b.max_version
order by a.id;
 
@AlbertLast
Bevor du das nächste Mal den dicken Max raushängen lässt, solltest du dich besser informieren.

AlbertLast schrieb:
ist auch klar das die kurz version nicht funktioniert
Sicher funktioniert das! Aber nur unter der von mir genannten Voraussetzung.

AlbertLast schrieb:
aber die langversion sollte funtionieren
Es sollte nicht nur funktionieren, es funktioniert garantiert!

AlbertLast schrieb:
das "inner" vor join ist auch unnötig.
Falsch, ein alleinstehendes "JOIN" gibt es nicht und würde auch wenig Sinn machen, weil zu es zu unpräzise ist!
Die meisten(!) SQL-Datenbanken erweitern ein einzelnes "JOIN" lediglich automatisch intern durch ein "INNER JOIN"
und gehen somit davon aus, dass die gesuchten Attributwerte in beiden Tabellen vorkommen müssen.
 
Zuletzt bearbeitet:
der sql 2003? standard sagt glaube ich das ein join default inner ist
daher machen das nicht einige sondern alle.
bzw wenn ein left,right oder full steht ein outer.

bei text ein max zu benutzen wirkt auf mich wie lotto...
 
Zurück
Oben