MySQL



  • Also bei mir bewirkt auch hier das LIMIT 1, dass nur eine einzige Zeile ausgegeben wird und nicht eine pro Projekt-ID 🙄



  • Vielleicht noch ein "GROUP BY cp.project_id" dabei ?

    Folgende Tabellen:
    
    Tabelle "projekte"
    id	projektname
    1	Ping
    2	Pong
    
    Tabelle "history"
    id 	projekt_id	tstamp
    1	2		7823923
    2	2		2147483647
    3	1		3829382
    4	2		72837132
    
    MySQL-Query:
    SELECT projekte.id as id,projekte.projektname as name, MAX(history.tstamp) as tstamp 
    FROM projekte
    LEFT  JOIN history ON ( projekte.id = history.projekt_id ) 
    GROUP BY projekte.id
    ORDER BY projekte.id ASC
    
    Liefert:
    id	name	tstamp
    1	Ping	3829382
    2	Pong	2147483647
    


  • Ich dachte er wollte nur eine Zeile. Hab ich dann falsch verstanden? LIMIT 1 liefert auch nur eine Zeile aus der Ergebnismenge.



  • @geeky
    So würde meine Lösung auch aussehen. Nur dass ich auch projektname in den GROUP BY mit aufnehmen würde 😉



  • Jo, wenn man aus der History-Tabelle nur das Datum benötigt geht das so - aber was macht man, wenn man auch noch die anderen Werte aus der History-Tabelle (von der Zeile mit dem neusten Datum) haben will?! Geht das überhapt 😕

    Oder müsste man dazu erst Datum und ID auslesen und dann nachher in weiteren Anfragen dazu die ganzen Datensätze holen 🙄



  • Ich glaube ich hab da etwas Verwirrung gestiftet:
    Ich brauche von jedem Projekt den letzten History Eintrag, aber danke schon mal an alle fürs Helfen.

    Für Oracle weiß ich eine Lösung, die aber erst ab MYSQL 4.0 geht, da es dort erst "UNION" gibt.



  • Aja verstehe. Eine Umgehung mit einem SQL-Befehl der UNION gibts leider nicht. Du müsstest also die Einträge deiner aktuellen Projekttabelle und die Einträge deiner Historytabelle jeweils mit einem SQL-Befehl holen. Bei der UNION hast du ja eigentlich eh zwei SELECTS, die schon das tun müssten was du brauchst. Also einfach aufsplitten und zweimal eine Abfrage senden und die Ergebnismenge in ein gemeinsames Array z. B. speichern ;).

    @flenders
    Du kannst gleich alles rausholen. Allerdings musst du hald jedes einzelne Feld extra angeben und alle Felder die keine sog. Agregatfunktion (wie max(), min(), sum(), ...) haben, müssten beim GROUP BY auftauchen. Etwas umständlich also und bei vielen Feldern ist es wahrscheinlich besser, sich nur den Primärschlüssel zu holen und dann die restlichen Daten über extra Abfragen zu bekommen.



  • Reicht ein GROUP BY für die Projekt-ID nicht aus ?



  • @AJ: Irgendwie verstehe ich das nicht so ganz 🙄 Wie kann ich denn konkret aus der history für jede Projekt-ID jeweils den kompleten Datensatz mit dem neusten Datum holen (mit einem einzigen SELECT) 😕



  • (Verfluchte Tab-Stops, da nochmal: http://www.geeky.de/stuff/mysql.txt)

    Gehen wir mal von diesen beiden Tabellen aus:

    Tabelle "projekte"
    id projektname
    1 Ping
    2 Pong

    Tabelle "history"
    id projekt_id tstamp
    1 2 7823923
    2 2 2147483647
    3 1 3829382
    4 2 72837132

    SELECT projekte.id as id,projekte.projektname as name, MAX(history.tstamp) as tstamp
    FROM projekte
    LEFT JOIN history ON ( projekte.id = history.projekt_id )
    GROUP BY projekte.id
    ORDER BY projekte.id ASC
    

    MySQL macht dann vermutlich folgendes:
    Erstmal beide Tabellen anhand von "ON (projekte.id=history.projekt_id)" zu einer verbinden:

    Tabelle temporär ;D
    projekte.id	projekte.projektname	history.id	history.projekt_id	history.tstamp
    1    		Ping			3		1			3829382
    2    		Pong			1		2			7823923
    2		Pong			2		2			2147483647
    2		Pong			4		2			72837132
    

    Nun soll MySQL mittels der MAX()-Funktion den größten Timestamp pro projekt.id raussuchen (denn danach sollen die Einträge
    gruppiert werden ("GROUP BY projekte.id"), daher kommen jetzt nur noch 2 Zeilen übrig:

    Tabelle temporär2 ;D
    projekte.id	projekte.projektname	history.id	history.projekt_id	history.tstamp
    1    		Ping			3		1			3829382
    2		Pong			2		2			2147483647
    

    ...und da nur projekte.id als 'id', projekte.projektname als 'name' und der größte Timestamp pro projekt.id als 'tstamp'
    selektiert wurden, liefert MySQL letztendlich das:

    id	name	tstamp
    1    	Ping	3829382
    2	Pong	2147483647
    

    Wenn man noch mehr Felder aus der Zeile mit dem größten timestamp braucht, muss man sie nur beim select mit angeben.
    Wenn man z.B. in der history-tabelle noch eine Spalte 'aktion' hat und die auch haben will muss nur noch ein
    history.aktion as 'aktion' mit angegeben werden und MySQL liefert eine 'aktion'-Spalte mit aus...

    Keine Ahnung ob ich das so richtig verstanden hab, aber zumindest funzt die Query 😉



  • geeky schrieb:

    Wenn man z.B. in der history-tabelle noch eine Spalte 'aktion' hat und die auch haben will muss nur noch ein history.aktion as 'aktion' mit angegeben werden und MySQL liefert eine 'aktion'-Spalte mit aus...

    Genau hier liegt mein Problem - bei mir wird dann eben nicht die zum Max-Datum gehörige aktion ausgegeben, sondern "zufällig" eine aus den ganzen aktionen dieser ID 🙄



  • http://www.mysqlfreaks.com/statements/27.php
    ...demnach scheint MAX() nicht das zu tun was es soll.
    Welchen Datentyp hat denn deine Datum-Spalte ? (Wobei wenn MAX() mit dem Datentyp nicht umgehen kann dürfte MySQL nen Fehler melden oder ?!)



  • Den Zusammenhang verstehe ich jetzt nicht so gnaz 🙄



  • @flenders
    Kannst du mal deinen SELECT zeigen, die Daten deiner Tabellen und was du als Ergebnis bekommst?



  • id  date        val1       val2  
    1   2003-01-01  valprim1   valprim2 
    1   2004-01-01  valprim3   valprim4 
    1   2004-05-06  valprim10  valprim20 
    2   2003-08-09  sdf        sdfsdf
    

    "SELECT * FROM history GROUP BY id" liefert folgendes:

    id  date        val1       val2  
    1   2003-01-01  valprim1   valprim2 
    2   2003-08-09  sdf        sdfsdf
    

    "SELECT id, MAX( date ) , val1, val2 FROM history GROUP BY id" liefert jetzt zwar das richtige Datum, aber eben nicht die dazugehörigen val1 und val2 Werte, sondern die wie oben 🙄



  • Wie wärs mit:

    SELECT id, max(datum), val1, val2 FROM history GROUP BY id, val1, val2
    

    Nachtrag:
    Gerade ist mir eingefallen, dass das so trotzdem nicht geht. Du hast recht flenders, du musst dir zuerst die id holen und kannst dir dann erst mit dieser die restlichen (korekten) Daten holen.



  • Sorry, hatte das am Anfang wohl falsch gelesen.

    Wenn du zu jeder Projekt-ID das max(datum) haben willst kommst du imho in mysql momentan nicht um einen extra-select zum auslesen jeder id mit dem entsprechenden maxdatum herum.
    Ich finde das verhalten von mysql nur ziemlich komisch. Sollte es nicht eigentlich abbrechen wenn ein Feld weder von einer Aggregatfunktion umschlossen noch im group-by steht? Dann einfach irgendwas zurückzugeben finde ich ziemlich sch... von mysql 🙄

    Und natürlich gibt limit 0,1 immer nur einen Datensatz zurück 🙂



  • Ja eigentlich sollte es der SQL-Interpreter anmeckern, aber auch dann würden nicht die richtigen Daten geliefert werden. Ich vermute mal, dass mysql automatisch die Felder ohne Aggregatfuntion in die Liste des GROUP BY mitaufnimmt.



  • Das kann ja nicht sein. Dann würde man mehr ergebniszeilen zurückbekommen, da ja nach mehr bedingungen gruppiert wird.

    aber (scheinbar) wahrlos einen Wert anzuzeigen find ich sehr gefährlich 😮



  • Natürlich kann man das ganze auch in MySQL mit einer SQL-Query lösen. Man muss nur ein bißchen tricksen:

    Nehmen wir an, die Tabellen sind definiert wie folgt:

    CREATE TABLE projekte
    (
      id INT(11) AUTO_INCREMENT,
      name VARCHAR(50),
      PRIMARY KEY(id)
    );
    
    CREATE TABLE history 
    (
      pid INT(11) NOT NULL,
      aktion VARCHAR(50),
      zeit TIMESTAMP
    );
    

    Dann liefert folgende Query

    SELECT p.id,p.name,h1.aktion,h1.zeit FROM projekte p INNER JOIN history h1 ON p.id=h1.pid LEFT JOIN history h2 ON h1.zeit<h2.zeit AND h1.pid=h2.pid WHERE h2.zeit IS NULL ORDER BY p.name;
    

    einwandfrei die letzten Aktionen zusammen mit den jeweiligen Daten des Projektes. Durch den Self-Join ist das ganze intern zwar relativ aufwendig, bei richtigen Indizees, sollte sich das ganze aber noch im Rahmen des erlaubten bewegen.

    Gruß Jens


Anmelden zum Antworten