Timo Schwarz: Abfrage mit Bezug zum letzten Datensatz, geht sowas?

Hallo,

meine DB-Struktur sieht ungefähr so aus:

ID(int,autoincrement)-User(varchar)-Datum(datetime)-Seite(varchar)

Ich suche alle Datensätze:

  • eines Users mit dem Namen 'XYZ'
  • ohne das die Datumsspalte den ersten Eintrag des Tages zeigt
  • mit Seite 'test.php'
  • ohne Seite 'trallala.php' des vorherigen Datensatzes dieses Users
  • mit Zeitdifferenz des aktuellen zum vorhergehenden Datensatzes von mehr als 1 Std.

Schön wäre, den Usernamen, das Datum und die Zeitdifferenz zum Vordatensatz als Ergebnis zu bekommen.

Geht das in einer Query oder sollte ich mir das lieber in php selber zusammenbasteln

Schönen Gruß

Timo

  1. Hi!

    Ich suche alle Datensätze:

    • eines Users mit dem Namen 'XYZ'
    • ohne das die Datumsspalte den ersten Eintrag des Tages zeigt
    • mit Seite 'test.php'
    • ohne Seite 'trallala.php' des vorherigen Datensatzes dieses Users
    • mit Zeitdifferenz des aktuellen zum vorhergehenden Datensatzes von mehr als 1 Std.

    Fehlt da als Kriterium noch, dass nur ein einzelner Tag gewünscht ist? Und wie muss ich "ohne Seite 'trallala.php' des vorherigen Datensatzes dieses Users" deuten?

    Schön wäre, den Usernamen, das Datum und die Zeitdifferenz zum Vordatensatz als Ergebnis zu bekommen.

    Der vorhergehende Datensatz lässt sich nicht einfach ermitteln. Zunächst erst einmal wäre zu klären, wie du "vorhergehenden Datensatz" definierst. Ist es der mit der mit dem größten Zeitwert aus der Menge derer, deren Zeitwert kleiner als der vom aktuellen Datensatz ist? Oder das selbe Prinzip aber mit der ID - wobei anzumerken ist, dass die ID üblicherweise nicht die Aufgabe hat, eine Reihenfolge sicherzustellen sondern nur eine eindeutige Identifikation. Deshalb sollte man auch nicht davon ausgehen, dass Zahlenwerte als ID lückenlos vorhanden sind. Sonst müsste man einfach nur aktuelle ID minus Eins nehmen.

    Geht das in einer Query oder sollte ich mir das lieber in php selber zusammenbasteln

    Der vorhergehende sollte sich mit einer Subquery ermitteln lassen. Wobei es da doch eine Einschränkung gab, dass MySQL LIMIT in einer Subquery nicht oder zumindest nicht in alle Fällen unterstützt, wenn ich mich recht erinnere. Aber Lösungen für "vorhergehenden Datensatz" gibt es schon im hiesigen Archiv. Du kannst ja mal schauen, ob du da was passendes findest.

    Wenn du nur einen Tag abfragst und den ersten Eintrag des Tages nicht willst, kannst du den ja mit LIMIT überspringen. Wenn es mehrere Tage sind, fällt mir keine Lösung ein, wie man den jeweils gleich beim Abfragen von der Selektion ausschließen kann (jedenfalls nicht ohne den Aufwand einer Stored Procedure).

    Das Kriterium "von mehr als einer Stunde" müsste meines Erachtens in einer HAVING-Klausel abgearbeitet werden. Die Subquery für den vorhergehenden Datensatz steht ja in der SELECT-Klausel und die wird erst nach dem WHERE ausgewertet. Also kann im WHERE kein Kriterium stehen, das erst danach berechnet wird. Oder aber, dich interessiert der Wert der Zeitdifferenz nicht, dann kannst du die Subquery in der WHERE-Klausel unterbingen.

    Lo!

    1. Hallo dedlfix,

      Fehlt da als Kriterium noch, dass nur ein einzelner Tag gewünscht ist? Und wie muss ich "ohne Seite 'trallala.php' des vorherigen Datensatzes dieses Users" deuten?

      Nein, eigentlich suche ich es sogar nach Tagen sortiert.

      Ohne Seite 'tralalla.php' heißt, dass der Datensatz, selbst wenn alles andere passt, nicht zhur Ergebnismenge gehört, wenn sich in der Spalte 'Seite' des Vordatensatzes der Eintrag 'tralala.php' befindet.

      Zunächst erst einmal wäre zu klären, wie du "vorhergehenden Datensatz" definierst. Ist es der mit der mit dem größten Zeitwert aus der Menge derer, deren Zeitwert kleiner als der vom aktuellen Datensatz ist? Oder das selbe Prinzip aber mit der ID...

      Beides richtig, solange es auf den User 'XYZ' bezogen bleibt.

      Wenn du nur einen Tag abfragst und den ersten Eintrag des Tages nicht willst, kannst du den ja mit LIMIT überspringen. Wenn es mehrere Tage sind, fällt mir keine Lösung ein, wie man den jeweils gleich beim Abfragen von der Selektion ausschließen kann (jedenfalls nicht ohne den Aufwand einer Stored Procedure).

      Richt ziemlich danach, dass ich mir das in PH bastel, stimmts? Denn ich brauch sicher mehr als 1 Tag.

      Schönen Gruß, Timo

      1. Hi!

        Richt ziemlich danach, dass ich mir das in PH bastel, stimmts? Denn ich brauch sicher mehr als 1 Tag.

        Ich denke, dass du einen Teil im PHP machen musst und den anderem im DBMS machen kannst. Das Statement wird dann aber recht komplex.

        Fehlt da als Kriterium noch, dass nur ein einzelner Tag gewünscht ist? Und wie muss ich "ohne Seite 'trallala.php' des vorherigen Datensatzes dieses Users" deuten?
        Nein, eigentlich suche ich es sogar nach Tagen sortiert.

        Dann fällt mir nichts anderes ein, als beim Ergebnisabfragen mit einem sogenannten Gruppenwechsel auf dem Datum zu arbeiten. Immer wenn die Gruppe (sprich: das Datum) wechselt, musst du einen Datensatz ignorieren, um das Kriterium "ohne ersten Datensatz des Tages" zu erfüllen.

        Ohne Seite 'tralalla.php' heißt, dass der Datensatz, selbst wenn alles andere passt, nicht zhur Ergebnismenge gehört, wenn sich in der Spalte 'Seite' des Vordatensatzes der Eintrag 'tralala.php' befindet.

        Subselect im WHERE oder Subselect im SELECT nebst Kriteriumsauswertung im HAVING schwebt mir da vor.

        Es wäre noch zu klären, ob du Werte vom Vordatensatz in der Ergebnismenge haben willst (auch solche, die zum Berechnen Vordatensatzwerte benötigen) oder ob der nur als Auswahlkriterium dienen soll. Nur als Auswahlkriterium kann die Subquery im WHERE stehen. Sie kann dann auch mehr als einen Wert zurückgeben, der verglichen werden soll (Row Subquery. Der Vergleich muss dann aber für alle Werte mit dem selben Operator durchzuführen sein. Ein Wert mit =, der andere mit < geht beispielsweise nicht.) Im SELECT-Teil jedenfalls kann eine Subquery immer nur einen einzelnen Wert liefern. Braucht man mehrere Werte, kann sie nur im FROM stehen, kann aber keine Correlated Subquery sein sondern muss mit der anderen Tabelle gejoint werden.

        Zunächst erst einmal wäre zu klären, wie du "vorhergehenden Datensatz" definierst. Ist es der mit <del>der mit</del> dem größten Zeitwert aus der Menge derer, deren Zeitwert kleiner als der vom aktuellen Datensatz ist? Oder das selbe Prinzip aber mit der ID...
        Beides richtig, solange es auf den User 'XYZ' bezogen bleibt.

        Da die Einschränkung auf den User Lücken in die Nummerierung der IDs reißt, ist die einfache Formel vor = akt.id -1 gleich gar nicht verwendbar. Bleibt noch die lange Variante, die ich ja schon passend zu formulieren versucht habe. Du musst sie "nur noch" in Code übersetzen.

        Lo!