MySQL



  • ich hab eine Frage wegen SQL/Mysql

    folgendes Problem

    Ich habe eine Tabelle, wo Projekte verwaltet werden.
    Dazu gibt es eine zweite Tabelle wo die History Einträge der entsprechenden Projekte verwaltet werden
    (und zwar alle die jemals geschrieben würden).
    In der History Tabelle ist eine Spalte die mit einem FOREIGN KEY die Projekt ID enthält.
    Nun möchte ich die zwei Tabellen miteinander (left join) verbinden. Allerdings will ich von
    jedem Projekt nur den letzten Eintrag (die History Tabelle hat eine Spalte Datum).

    select * from project cp left join history ch on (cp.project_id=ch.Company_history_project_id)

    Company_history_project_id ist der FOREIGN KEY.

    kann ich das irgendwie mit "where" lösen?



  • So könnte es vielleicht gehen:

    select * from project cp left join history ch on (cp.project_id=ch.Company_history_project_id) 
    order by datum desc limit 0,1
    

    ich wüsste noch ne andere Möglichkeit, aber die benötigt
    subselects, die es ja in mysql nicht gibt.

    geht aber bestimmt auch noch schöner.. (hoffe ich *g*)



  • Tow-B.de schrieb:

    So könnte es vielleicht gehen:

    select * from project cp left join history ch on (cp.project_id=ch.Company_history_project_id) 
    order by datum desc limit 0,1
    

    ich habe vorhin auch mal eine Weile herumgetüftelt, bin aber daran gescheitert. Ich kann mir nicht vorstellen, dass dein Code so funktioniert, denn der gibt doch wohl nur eine einzige Zeile aus, oder?
    Aber ich habe es sogar nichtmal hinbekommen nur aus der Historytabelle direkt für jede ID die Zeile mit dem neusten Datum auszulesen 🙄 😞



  • select ch.* from project cp,history ch where cp.project_id=ch.Company_history_project_id order by datum desc limit 1



  • 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.


Anmelden zum Antworten