bense: Neuester Eintrag aus 2 Spalten

Guten Morgen!

Ich habe eine MySQL-DB in der ich eine Tabelle mit 2 Timestamp-Spalten habe. Jetzt bräuchte ich ich den Eintrag mit dem neuesten Timestamp aus beiden Spalten.

Zur Erklärung: Wenn ich jetzt 2 Einträge hätte, dann hätte ich ja insgesamt 4 Timestamps. Jetzt möchte ich nach dem neuesten aller 4 Timestamps suchen und dann den entsprechenden Eintrag ausgeben. Mit order ist mir keine Lösung eingefallen, da ich ja irgendwie alle 4 Timestamps vergleichen müsste.

Ich hoffe, es ist einigermassen klar, was mein Problem ist...

Danke und Gruss

  1. Hello,

    Ich habe eine MySQL-DB in der ich eine Tabelle mit 2 Timestamp-Spalten habe. Jetzt bräuchte ich ich den Eintrag mit dem neuesten Timestamp aus beiden Spalten.

    Das ist eine spannende Frage, da horizontale Abfragen gar nicht gut funktionieren.

    Da wirst Du wohl zwei Abfragen benötigen, und die Ergebnisse dann nochmal vergelichen müssen.

    select ID, max(T1) as T1max from table group by T1 order by T1max desc limit 0,1 ;

    Und das gleiche dann mit T2

    Was besseres fällt mir derzeit nicht ein.

    Harzliche Grüße aus http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau
    1. Hello,

      select ID, max(T1) as T1max from table group by T1 order by T1max desc limit 0,1 ;

      Das war jetzt im Kreis rumgedacht:

      select ID, T1 from table order by T1 desc limit 0,1 ;

      reicht da natürlich auch, um den größten einer Spalte zu suchen

      Harzliche Grüße aus http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
  2. yo,

    Ich hoffe, es ist einigermassen klar, was mein Problem ist...

    du musst dafür eine verzweigung zweier spalten vornehmen. mysql kennt für so etwas die if funktion. zum anderen musst du dir klar machen, ob du nur das datum brauchst oder auch andere werte des jeweiligen datensatzes. ferner ist zu überlegen, wie man vorgehen will, wenn mehrere datensätze den gleichen größten zeitstempel haben. aber mal ein kleine query, falls dir der größte zeitstempel reicht.

    SELECT max(if(zeitspalte1 > zeitspalte2, zeitspalte1, zeitspalte2)) FROM tabelle

    Ilja

    1. Hello,

      SELECT max(if(zeitspalte1 > zeitspalte2, zeitspalte1, zeitspalte2)) FROM tabelle

      Soweit war ich auch schon. Aber das würde ja heißen, dass erst der Vergleich innerhalb der Zeile und aus dieser Ergebnismenge dann der größte Wert gesucht wird.

      Wie machst Du das denn, wenn Du aus mehreren Spalten gleichen Typs (Was ja schon wieder Normalisierung erforderlich gemacht hätte) den insgesamt größten oder kleinsten Wert suchst.

      Harzliche Grüße aus http://www.annerschbarrich.de

      Tom

      --
      Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
      Nur selber lernen macht schlau
      1. yo,

        Aber das würde ja heißen, dass erst der Vergleich innerhalb der Zeile und aus dieser Ergebnismenge dann der größte Wert gesucht wird.

        wenn ich seine frage richtig verstanden habe, dann sucht er genau nach diesem größten wert.

        Wie machst Du das denn, wenn Du aus mehreren Spalten gleichen Typs (Was ja schon wieder Normalisierung erforderlich gemacht hätte) den insgesamt größten oder kleinsten Wert suchst.

        sicherlich geht das genauso, indem man halt zwei spalten mit ausgibt, einmal mit min() und einmal mit max(). die jeweilige if funktion muß dann ensprechend ein größer oder kleiner zeichen besitzen. sollten es mehr als zwei spalten sein, kann man eventuell die case funktion benutzen oder aber mehrere if funktionen ineinander verschachteln.

        Ilja

        1. Hallo!

          Eigentlich bräuchte ich den ganzen Eintrag.

          Aber ehrlichgesagt blicke ich da noch nicht ganz durch. Ich brauche den Eintrag, der einfach den neuesten Timestamp der gesamten Table enthält. Also quasi die ganze Zeile ausgeben, in der der insgesamt neueste Timestamp aus beiden Spalten enthalten ist.

          Das ist irgendwie schwer zu erklären...

          Gruss

          1. yo,

            Ich brauche den Eintrag, der einfach den neuesten Timestamp der gesamten Table enthält.

            dann gibt es zwei möglichkeiten. entweder du benutzt die GROUP BY klausel. dort müssen dann alle spalten stehen, die du neben den aggregat-funktionen mit ausgeben willst. oder aber du benutzt unterabfragen. allerdings unterstützt nicht jede version von mysql unterabfragen, sondern erst due neueren.

            Ilja

            1. Wenn man es genau nimmt, bin ich jetzt noch verwirrter. Erstens, subselects kann ich nicht benutzen, da es nicht unterstützt wird. Zur zweiten Möglichkeit: Du meinst dein vorheriges Statement und dann hintenran noch GROUP BY? Dann kommt gar nichts gescheites raus. Und mit normalem Group by lässt sich mein Problem ja auch nicht lösen, ich kann ja nicht innerhalb 2 Spalten sortieren, sondern nur nacheinander.

              Sorry, vielleicht bin ich etwas schwer von Begriff, aber ich habe im Moment echt einen "Knopf"...

              1. yo,

                Sorry, vielleicht bin ich etwas schwer von Begriff, aber ich habe im Moment echt einen "Knopf"...

                nee, mit den group by geht es auch nicht so einfach. war mein fehler. und ohne unterabfragen wird es schwierig, wenn du nicht nur den kleinsten timestamp haben willst, sondern noch zusätzliche spalten anzeigen willst.

                Ilja

                1. yo,

                  also der einfachste weg wären unterabfragen. aber um noch mal ein wort zu der group by lösung zu verlieren, die nicht ganz so trivial ist. wenn du also mehrere werte brauchst, sprich nicht nur den größten timestamp aus beiden spalten, dann musst du als erstes über die spalten gruppieren, die du angezeigt haben willst. und dann in der HAVING klausel die aggregat und die IF funktion verwenden, die ich dir gezeigt habe. ob das wirklich so funktioniert, muss man einfach mal ausprobieren.

                  am besten ist, du gibst uns mal den tabellen-aufbau und sagst uns, welche spalten davon du angezeigt haben willst.

                  Ilja

                  1. id | anfang | ende | kunde | eintragstyp |
                    ------------------------------------------

                    id ist auto_increment. in anfang und ende stehen eben die betreffenden timestamps. in kunde ist eine eindeutige kundennummer. das kommt noch hinzu, ich will nur die Einträge durchsuchen, welche eine bestimmte Kundennummer haben.

                    Schlussendlich bräuchte ich anfang, ende und eintragstyp.

                    1. Ich glaube ich hab's. Wäre möglich, dass da funktioniert? Will nur vorbeigen, damit ich keine Überraschungen erlebe:

                      SELECT *
                      FROM zeiten
                      ORDER BY IF (
                      anfang > ende, anfang, ende
                      ) DESC
                      LIMIT 1

                      1. SELECT *
                        FROM zeiten
                        ORDER BY IF (
                        anfang > ende, anfang, ende
                        ) DESC
                        LIMIT 1

                        hey, super.
                        aber ich würds so versuchen:

                        SELECT
                        IF (anfang > ende, anfang, ende) as t
                        FROM zeiten
                        ORDER BY t DESC
                        LIMIT 1

                        rappelt natürlich die ganze tabelle ab, selbst wenn indizees drauf liegen.

                        1. yo,

                          SELECT *
                          FROM zeiten
                          ORDER BY IF (
                          anfang > ende, anfang, ende
                          ) DESC
                          LIMIT 1

                          hey, super.
                          aber ich würds so versuchen:

                          SELECT
                          IF (anfang > ende, anfang, ende) as t
                          FROM zeiten
                          ORDER BY t DESC
                          LIMIT 1

                          also, ich bin grundsätzlich mit mysql nicht so bewandert. aber aus dem bauch heraus würde ich sagen, keine der beiden funktioniert. es sei denn ihr habt es ausprobiert. erstens müsste eine aggregat funktion mit in das ORDER BY mit rein, es sein den, mysql macht das automatisch. das glaube ich aber nicht, wobei glauben nicht wissen ist. dann würde das so aussehen.

                          SELECT *
                          FROM zeiten
                          ORDER BY IF (max(anfang) > max(ende), anfang, ende) DESC
                          LIMIT 1

                          wenn das nicht geht, dann können wir uns meinen versuch mit GROUP BY und HAVING mal anschauen.

                          Ilja

                          1. Also meines scheint zu funktionieren.

                            SELECT *
                            FROM zeiten
                            ORDER BY IF (
                            anfang > ende, anfang, ende
                            ) DESC
                            LIMIT 1

                            Das funktioniert ja dann folgendermassen: ich ordne die gesamte Tabelle, wobei ich bei jedem Eintrag überprüfe, ob anfang oder ende grösser ist und anhand vom grösseren Wert wird dann geordnet. Am Schluss gebe ich nur den Grössten aus mit LIMIT 1. Ich denke, da ist eine ziemlich logische Lösung.

                            Danke für eure Hilfe!

                            1. yo,

                              Ich denke, da ist eine ziemlich logische Lösung.

                              das sehe ich ein wenig anders. es kann zufall sein, dass es funktioniert, quasi 50% chance. was das order by und limit angeht, so stimme ich dir zu, dass ist eine gute möglichkeit. ABER, in den beiden spalte mit den zeiten kommen nun mehrere datensätze vor, die miteinander verglichen werden. so wie du es geschrieben hast, nimmt er aber nur irgendeinen datensatz (vielleicht den ersten). und je nachdem welche spalte dabei größer ist führt er die sortierung durch. was meiner meinung nach nicht passiert, dass er nach den größten werten der jeweiligen spalte sucht und dann das entsprechende order by anwendet.

                              Ilja

                              1. Bist du da ganz sicher? Ich habe immer gedacht, wenn ich etwas mit ORDER BY ordne, dann vergleicht er das bei jedem Datensatz? Dann macht er ja jeden Datensatz durch, nicht?

                                1. yo,

                                  Bist du da ganz sicher? Ich habe immer gedacht, wenn ich etwas mit ORDER BY ordne, dann vergleicht er das bei jedem Datensatz? Dann macht er ja jeden Datensatz durch, nicht?

                                  erstens willst du es ja gar nicht bei jeden datensatz, sondern du willst nur den größten zeitwert der einen spalte mit den größten zeitwert der anderen spalte vergleichen. diese beiden max werte müssen aber nicht unbedinkt in gleichen datensatz stehen. und grundsätzlich wird eine tabelle nicht mal so und mal so zwischen den einzelnen datensätze in der ergebnistabelle sortiert. sondern die sortierung wird einmal vor der ausgabe der ergebnisliste festgelegt und dann erfolgt dem entsprechend eine sortierung der ergebnismenge.

                                  Ilja

                                  1. Also ich hab's jetzt ausgetestet, mit Höchstwert in der ersten und in der zweiter Spalte. Ich kann nur nochmals wiederholen: Meiner Meinung und den Tests nach müsste meine Lösung funktionieren. Aber ist ja auch egal, vielleicht erlebe ich ja dann doch noch eine böse Überraschung...

                                    1. yo bense,

                                      Also ich hab's jetzt ausgetestet, mit Höchstwert in der ersten und in der zweiter Spalte. Ich kann nur nochmals wiederholen: Meiner Meinung und den Tests nach müsste meine Lösung funktionieren. Aber ist ja auch egal, vielleicht erlebe ich ja dann doch noch eine böse Überraschung...

                                      nimm lieber die andere abfrage, die dir von fk aufgezeigt wurde. wenn dir ein beliebiger datensatz reicht, der den maximalwert besitzt, dann funktiniert die abfrage von fk auf jeden fall. bei deiner lösung habe ich zumindestens ein ungutes gefühl. wenn du aber alle datensätze bekommen willst, die den maxwert besitzen, musst du über group by gehen oder aber unterabfragen oder zwei queries draus machen.

                                      Ilja

                                      1. Aber wenn du das von fk genau anschaust, macht diese Abfrage haargenau dasselbe wie meine, nur dass er die if-Bedingung vorn in einen Alias verpackt. Also benutzt er genau auch bei ORDER BY eine if-Abfrage...

                                        1. ach ja, auch wenn das vielleicht in den letzten posts nicht gerade so rübergekommen ist, bin euch allen dankbar, dass ihr mich auf die richtige (oder eben auch nicht :)) lösung gebracht habt!

                                          vielen dank!

                                        2. yo,

                                          Aber wenn du das von fk genau anschaust, macht diese Abfrage haargenau dasselbe wie meine, nur dass er die if-Bedingung vorn in einen Alias verpackt. Also benutzt er genau auch bei ORDER BY eine if-Abfrage...

                                          der unterschied ist der, dass die if funktion mit alias mehrmals ausgeführt werden kann und zwar so oft wie es datensätze gibt. dabei wird die liste der ergebnisse erzeugt. das dbms nimmt einen datensatz, überprüft die where bedigungen und führt die funktion aus, um es dann in die ergebnisstabelle zu packen.

                                          die if funktion in der order by klausel wird aber nur ein einziges mal ausgeführt, wenn die ergebnisstabelle komplett ist. order by ist nichts anders als eine sortierung der ergebnisstabelle. selbst wenn es jedesmal ausgeführt auf die ergebnissmenge werden würde (was ist nicht glaube), quasi mit jedem datensatz dir sortierung neu erfolgen würde (was unendlich viel performance kostet), selbst dann würde nur eine sortierung gelten, nämlich die letzte. und die muss nicht immer die gewünschte sein.

                                          Ilja

                          2. Hello,

                            SELECT
                            IF (anfang > ende, anfang, ende) as t
                            FROM zeiten
                            ORDER BY t DESC
                            LIMIT 1

                            Das funktioniert auf jeden Fall.

                            Ich war vorhin nur irritiert, ob man nicht beide Spalten separat abfragen müsste, weil sie ja beide eine eigene Sortierung haben könnten. Aber das war nur ein Denkfehler. Es kommt ja nur ein einziger Wert heraus zum Schluss.

                            Harzliche Grüße aus http://www.annerschbarrich.de

                            Tom

                            --
                            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                            Nur selber lernen macht schlau
                            1. yo,

                              Das funktioniert auf jeden Fall.

                              das stimmt, der spalte ein alias zu geben und danach zu sortieren ist mir nicht eingefallen, obwohl es auf der hand liegt. naja, irren ist menschlich. also der abfrage würde ich nun doch meinen segen geben.

                              Ilja

                              1. yo,

                                Das funktioniert auf jeden Fall.

                                das stimmt, der spalte ein alias zu geben und danach zu sortieren ist mir nicht eingefallen, obwohl es auf der hand liegt. naja, irren ist menschlich. also der abfrage würde ich nun doch meinen segen geben.

                                nochmal eine ergänzung. letztlich funktioniert die query, aber nur mit der einschränkung, dass man nämlich immer nur einen datensatz bekommt. haben nur mehrere datensätze diesen maxwert, so wird trotzdem nur einer ausgeben. deswegen auch mal am anfang dieses postings mein hinweis, was genau er mit gleichen datensätzen machen will. wollte er nur den max haben, wärde es gegangen. aber ich gehe mal davon aus, der er eventuell alle datensätze mit diesen maxwert haben will. und dann geht diese lösung nicht mehr, sondern man muss über unterabfragen gehen odr aber über group by.

                                Ilja

                                1. Hello,

                                  nochmal eine ergänzung. letztlich funktioniert die query, aber nur mit der einschränkung, dass man nämlich immer nur einen datensatz bekommt. haben nur mehrere datensätze diesen maxwert, so wird trotzdem nur einer ausgeben. deswegen auch mal am anfang dieses postings mein hinweis, was genau er mit gleichen datensätzen machen will. wollte er nur den max haben, wärde es gegangen. aber ich gehe mal davon aus, der er eventuell alle datensätze mit diesen maxwert haben will. und dann geht diese lösung nicht mehr, sondern man muss über unterabfragen gehen odr aber über group by.

                                  Ja, ich habe auch den Eindruck, dass das Design von bense noch nicht endgültig ist. Vielleicht bringen ihn unsere kleinen Denkeskarpaden noch auch einen Denkfehler seinerseits - vielleicht. Sie könnten ihn aber auch in seinen Überlegungen bestätigen.

                                  Übrigens habe ich die Erfahrung gemacht, dass es machnmal sehr nützlich ist, sich diese Detaildiskusssionehn auszudrucken und beim Auftrag (wenn es für einen Kunden ist) abzulegen. Es ist mir schon zweimal passiert, dass der Kunde meinte, ich hätte wohl nicht genügend über die Möglichkeiten nachgedacht. Da habe ich dann nur die Mappe gezogen und ihnen kurzen Einblick in die Threads gewährt. Da waren sie dann still und einverstanden.

                                  Self ist also nicht nur gut zum lernen, sondern richtig angewandt auch eine gute Versicherung.

                                  Harzliche Grüße aus http://www.annerschbarrich.de

                                  Tom

                                  --
                                  Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                                  Nur selber lernen macht schlau
          2. Hello,

            Ich brauche den Eintrag, der einfach den neuesten Timestamp der gesamten Table enthält. Also quasi die ganze Zeile ausgeben, in der der insgesamt neueste Timestamp aus beiden Spalten enthalten ist.

            Dann mache es so, wie ich sagte:

            lock tables $table read;  # fragen ob es geklappt hat!
              select id, time1 from $table order by time1 desc limit 0,1;
              select id, time2 from $table order by time2 desc limit 0,1;

            unlock tables; ## ggf auch erst am Ende der gesamten Verarbeitung

            und dann mit PHP oder Perl die beiden results abholen und einfach vergleichen, welcher
              Timestamp der größere ist und die ID als Ergebnis der Funktion zurückgeben.

            Wenn das DBMS Stored Procedures kann, kann man das auch dort vergleichen lassen.

            Das Ergebnis ist natürlich nur der Snapshot zur Gültigkeitszeit, als das Lock
              gesetzt wurde. Sowie das Unlock gesendet wird, Endet der Gültigkeitsbereich
              des Ergebnisses. Wenn das Ergebnis dazu dienen soll, irgendwo Daten zu verändern,
              muss man mit Write-Lock arbeiten, auch wenn in dieser Tabelle gar nicht geschrieben
              wird. Das gilt natürlich nur für den konkurrierenden Betrieb, aber den hat man bei
              Internetapplikationen ja meistens.

            Harzliche Grüße aus http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau
  3. Ich habe eine MySQL-DB in der ich eine Tabelle mit 2 Timestamp-Spalten habe. Jetzt bräuchte ich ich den Eintrag mit dem neuesten Timestamp aus beiden Spalten.

    versuchs mal so:

    select max(max(ts1), max(ts1)) from tabelle

    1. tschuldigung, alles zurück.

      max ist ja nur eine aggregatsfunktion, somit nur auf eine spalte anwendbar.

      es geht wohl nur über ein subselect, welches 2 max spalten liefert,
      und in dem übergeordneten select per if die beiden spalten vergleichen.

      1. Hello,

        max ist ja nur eine aggregatsfunktion, somit nur auf eine spalte anwendbar.

        Und in MySQL nur mit "group by" verwendbar

        Harzliche Grüße aus http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau
        1. Hello,

          max ist ja nur eine aggregatsfunktion, somit nur auf eine spalte anwendbar.

          Und in MySQL nur mit "group by" verwendbar
          wenn man mehr als eine Spalte abfragt.

          Habe ich doch wieder zu schnell auf Return geklickt.

          Harzliche Grüße aus http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau
          1. max ist ja nur eine aggregatsfunktion, somit nur auf eine spalte anwendbar.

            Und in MySQL nur mit "group by" verwendbar
            wenn man mehr als eine Spalte abfragt.

            hey, sei nicht so pingelig. ich meine eine spalte nicht als menge, sondern als eigenschaft. allerdings gibt die aggregierte spalte nur eine zeile als ergebnis. deshalb müssen die anderen spalten in gruppen gefaßt werden. (mysql ist hier etwas toleranter).

            wenn du die aggretierte spalte gruppierst, erhälst du mehr als eine ergebniszeile, je nach dem wie viele unterschiedliche ausprägungen es gibt. (läßt sich dann ja auch mit distinct erreichen).

            1. yo,

              deshalb müssen die anderen spalten in gruppen gefaßt werden. (mysql ist hier etwas toleranter).

              mysql ist hier keineswegs toleranter, sondern überläßt das denken den benutzern. man kann in mysql nämlich das einsetzen in die GROUP BY spalten nur dann weglassen, wenn diese spalte auch eindeutig ist, sprich nur einen wert hat. und genau dabei passiert vielen der fehler.

              so besteht der unterschied darin, dass bei allen anderen dbms durch das explizite angeben in der group by klausel sichergestellt wird, dass diese spalte nur einen wert besitzt und somit mit einer aggregat-funktion mit angezeigt werden kann. und bei mysql muss der benutzer das von sich aus sicherstellen, dass diese spalte nur einen wert hat. der grund für diese mysql eigenart ist nicht damit toleranter umzugehen, sondern die performance zu steigern, damit man sich sortierungsvorgänge erpsarrt.

              Ilja

              1. so besteht der unterschied darin, dass bei allen anderen dbms durch das explizite angeben in der group by klausel sichergestellt wird, dass diese spalte nur einen wert besitzt und somit mit einer aggregat-funktion mit angezeigt werden kann. und bei mysql muss der benutzer das von sich aus sicherstellen, dass diese spalte nur einen wert hat. der grund für diese mysql eigenart ist nicht damit toleranter umzugehen, sondern die performance zu steigern, damit man sich sortierungsvorgänge erpsarrt.

                ja, ja, wem sagst du das.
                mit unserem liebem db2 muß ich manchmal tierisch rumtrixen, bis ich dann herausgefunden habe, das eine funktion in den argumenten eine leerstelle verlangt. ist zwar merkwürdig, aber ohne leerstelle meckert der. der ist halt mehr als nur 'superpingelig'.

                1. yo,

                  der ist halt mehr als nur 'superpingelig'.

                  naja, manchmal macht es aber auch sinn, ein wenig pingelig zu sein. aus den erfahrungen hier bei selfhtml kommt es oftmals eben genau deshalb zu fragen, weil mysql eben mit group by nicht so pingelig ist, obwohl es eigentlich doch wiederum ist. mysql setzt es genauso vorraus, nur angeben muss man es nicht. mich würde es nicht wundern, wenn mysql bald wieder superpingelig wir und ich würde das in diesem falle als fortschritt ansehen. ;-)

                  Ilja