Treziman: Gezielte Tabellenabfrage

Hallo,
ich möchte Euch mit meinem Problem belästigen, da ich auf der Stelle trete. Es geht um eine Datenbank-/Tabellenabfrage, die nur die jeweils neuesten Einträge ausgeben soll. Genauer:
In meiner Tabelle stehen z.Zt. 3 Einträge (zum Testen):
1. Klaus, id = 3, text = test1
2. Dieter, id = 5, text = test2
3. Klaus, id = 7, text = test3

Das gewünschte Ergebnis bei Ausgabe müsste sein:
1. Klaus + test3
2. Dieter + test2

Hier mein Code:

  
$frage = mysql_query("select name,text from $tabelle where id = (select MAX(id) from $tabelle) GROUP BY name");  

Hier bekomme ich zwar das richtige Ergebnis geliefert, aber leider nur EINEN Eintrag, nämlich den 3. von Klaus. Sonst nix.

Und hierbei:

  
$frage = mysql_query("select name,text,MAX(id) from $tabelle GROUP BY name" );  

bekomme ich 2 Einträge (Dieter und Klaus), bei Klaus jedoch ist die ID richtig (7), der Text (test1) aber der falsche!

Für mich wäre wieder mal logisch, dass zur MAX(id) auch der dazugehörige Text geliefert wird. Scheint aber nicht so zu sein.
Kann mir jemand auf die Sprünge helfen?

Dankeschön!
Treziman

  1. Om nah hoo pez nyeetz, Treziman!

    Die ID eines Datensatzes hat keinerlei inhaltliche Bedeutung, sie dient lediglich der Identifikation des Datensatzes. Insbesondere ist der Datensatz mit der höchsten ID auch der zuletzt eingetragene.

    Speichere einen timestamp und verwende order by und limit.

    Matthias

    --
    Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Mond und Mondrian.

    1. @ dedlfix und Matthias

      Danke für Eure Antworten.

      Klar, die höchste ID hat auch das neueste Datum. Timestamp ist auch in der Tabelle, funktioniert damit aber auch nicht.

      Das Problem ist, dass ich von JEDEM Namen (userid ist auch zugeordnet, da Namen doppelt vorkommen könnten) NUR den neusten Eintrag brauche, also den mit dem höchsten Timestamp oder ID (ist auto_increment + unique). Zum Testen reichen aber die Namen.

      Probiere ich herum und versuche eine andere Syntax als in den Beispielen, bekomme ich grundsätzlich eine Fehlermeldung. Habe mit Codes aus dem Internet probiert - geht nicht, obwohl exakt abschrieben. Muss ich da mit INNER JOIN oder ähnlichem arbeiten?

      Lösen kann ich das ganze mit einer Schleife (jeweils neuestes Datum oder höchste ID einem Namen zugeordnet) und mehrfachen Abfrage, aber das ist ja wie Auto fahren zu Fuss.

      Treziman

      1. So, hab jetzt folgendes gemacht:

          
        "select absid,name,text,datum FROM $tabelle WHERE id IN(select MAX(id) FROM $tabelle GROUP BY absid)"  
        
        

        Jetzt geht es! Und ich hab Stunden herumprobiert!

        Ich sollte mich demnächst vielleicht eher an dieses Forum wenden.

        Vielen Dank Euch beiden!

        Treziman

      2. Om nah hoo pez nyeetz, Treziman!

        Klar, die höchste ID hat auch das neueste Datum. Timestamp ist auch in der Tabelle, funktioniert damit aber auch nicht.

        Ups, da fehlte in meiner Antwort was, und zwar ein „nicht unbedingt“. Du kannst dich NICHT darauf verlassen, dass der Datensatz mit der höchsten ID auch der zuletzt eingetragene ist. Das Datenbankmanagementsystem kann auch Lücken, die durch gelöschte Datensätze entstehen, wieder auffüllen.

        Du musst dir also zuerst von jedem nur einen Datensatz holen:

        GROUP BY `name`  
        
        

        Aber den jüngsten dieser Datensätze:

        SELECT MAX(`timestamp`) FROM `table` GROUP BY `name`  
        
        

        Jetzt hast du eine schöne Teilmenge deiner Datensätze, daraus sammelst du jetzt die gewünschten Daten heraus:

        SELECT `column` FROM `table` WHERE `timestamp` IN /*teilmenge*/  
        
        
        SELECT `column` FROM `table` WHERE `timestamp` IN  
               (SELECT MAX(`timestamp`) FROM `table` GROUP BY `name`)  
        
        

        Matthias

        --
        Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Kamas und Kamasutra.

        1. Tach!

          Du musst dir also zuerst von jedem nur einen Datensatz holen:
          Aber den jüngsten dieser Datensätze:
          Jetzt hast du eine schöne Teilmenge deiner Datensätze, daraus sammelst du jetzt die gewünschten Daten heraus:

          SELECT column FROM table WHERE timestamp IN

          (SELECT MAX(timestamp) FROM table GROUP BY name)

            
          Das gibt nur ein kleines Problem. Wenn die Timestamps nicht fein genug auflösen und zwei Einträge denselben Timestamp haben, der eine aber zu einer Gruppe gehört, die noch neuere Datensätze hat, dann kommen von der Gruppe zwei Datensätze in die Ergebnismenge.  
            
          Wenn man es richtig machen will und sich nicht auf die üblicherweise aber icht garantiert aufsteigend vergebenen Werte der IDs verlassen möchte, muss man den Gruppennamen und den Timestamp berücksichtigen. Dann kann man aber die Subquery nicht mehr ins WHERE nehmen, sondern ins FROM und muss joinen. Die Join-Bedingung muss beide Werte vergleichen.  
            
            
          dedlfix.
          
  2. Tach!

    ich möchte Euch mit meinem Problem belästigen, da ich auf der Stelle trete. Es geht um eine Datenbank-/Tabellenabfrage, die nur die jeweils neuesten Einträge ausgeben soll. Genauer:
    In meiner Tabelle stehen z.Zt. 3 Einträge (zum Testen):

    1. Klaus, id = 3, text = test1
    2. Dieter, id = 5, text = test2
    3. Klaus, id = 7, text = test3

    Das gewünschte Ergebnis bei Ausgabe müsste sein:

    1. Klaus + test3
    2. Dieter + test2

    Die neuesten Einträge? Ich seh da gar kein Datum. Der numerische Wert der ID ist keine Garantie für das Alter eines Datensatzes.

    Hier mein Code:
    $frage = mysql_query("select name,text from $tabelle where id = (select MAX(id) from $tabelle) GROUP BY name");

    PHP-Code interessiert an der Stelle nicht. Bitte weglassen und nur das SQL zeigen. Jedenfalls findet das WHERE eher statt als das GROUP BY. Die Abfrage kann nur einen einzigen Wert liefern. Das GROUP BY kann daran auch nichts mehr ändern.

    Hier bekomme ich zwar das richtige Ergebnis geliefert, aber leider nur EINEN Eintrag, nämlich den 3. von Klaus. Sonst nix.

    Und hierbei:
    $frage = mysql_query("select name,text,MAX(id) from $tabelle GROUP BY name" );
    bekomme ich 2 Einträge (Dieter und Klaus), bei Klaus jedoch ist die ID richtig (7), der Text (test1) aber der falsche!
    Für mich wäre wieder mal logisch, dass zur MAX(id) auch der dazugehörige Text geliefert wird. Scheint aber nicht so zu sein.

    Diese Syntax ist nur bei MySQL gültig. Üblich ist ansonsten, dass man beim Gruppieren nur die Spalten selektieren darf, über die man gruppiert hat oder auf die man Aggregatfunktionen angewendet hat. MySQL liefert für andere Felder einen x-beliebigen Wert aus der Gruppe. Stell dir vor, du verwendest MAX() und MIN(), welcher Wert soll dann in die Ergebnismenge kommen?

    Um dein Anliegen zu lösen, musst du zuerst die gesuchten IDs ermitteln und dann kannst du zu diesen die passenden Datensätze abfragen.

    SELECT felder FROM tabelle WHERE id IN(SELECT MAX(id) FROM tabelle GROUP BY ...)

    dedlfix.