signorpiccolo: Wie finde ich mit SQL den "am nächsten gelegenen" Wert?

Liebe Gemeinde,

wie finde ich mit SQL den Datensatz, dessen Wert in einer bestimmten Spalte einem vorgegeben Wert am nächsten ist?

Beispiel: Eine Tabelle, die unter "Wert" den Stand meines Stromzählers enthält und unter "Datum" den Timestamp des Ablesedatums (s.u.). Nach einem halben Jahr weiß ich natürlich nicht mehr, wann genau ich abgelesen habe. Also will ich wissen: Gib mir die Nummer des Datensatzes, dessen Datum am nächsten z.B. am 1.7.2006 dran liegt. Aber ich bin zu blöd. Könnt Ihr mir helfen? Danke!

+---------+-------+------------+
| ID      | Wert  | Datum      |
+---------+-------+------------+
| 1-59067 | 59067 | 1126476000 |
| 1-59460 | 59460 | 1141426800 |
| 1-59465 | 59465 | 1141599600 |
| 1-59492 | 59492 | 1142550000 |
| 1-59511 | 59511 | 1142982000 |
| 1-59586 | 59586 | 1146261600 |
| 1-59775 | 59775 | 1154692800 |
| 1-59813 | 59813 | 1155938400 |
| 1-59814 | 59814 | 1156111200 |
| 1-59831 | 59831 | 1156716000 |
| 1-59843 | 59843 | 1157320800 |
| 1-59853 | 59853 | 1157925600 |
+---------+-------+------------+

  1. Hallo,

    hier ist ein logischer Anschubser in der Hoffnung, dass du Rest selbst hinkriegst. Du suchst denjenigen Datensatz, dessen Datum die minimale Differenz von deinem vorgegeben Datum hat. Na kannst du das in SQL übersetzen?

    Cruz

    1. Du suchst denjenigen Datensatz, dessen Datum die minimale Differenz von deinem vorgegeben Datum hat. Na kannst du das in SQL übersetzen?

      Icke: Danke. Das habe ich schon versucht. Sah dann so aus:

      select min(abs(Datum-unix_timestamp('2006-7-1'))) from werte;

      Aber ich schaffe es nicht, mir gleichzeitig die Nummer (ID) des entsprechenden Datensatzes ausgeben zu lassen.

      1. Moin!

        select min(abs(Datum-unix_timestamp('2006-7-1'))) from werte;

        Aber ich schaffe es nicht, mir gleichzeitig die Nummer (ID) des entsprechenden Datensatzes ausgeben zu lassen.

        Wird auch schwierig, weil Aggregatfunktionen GROUP BY erfordern - und GROUP BY löst den Zusammenhalt zwischen Spalten auf.

        Sortiere einfach die Spalte der Differenzen aufsteigend, und nimm den ersten Wert. Das ist der kleinste. Parallel kannst du dann auch die ID nehmen.

        - Sven Rautenberg

        --
        "Love your nation - respect the others."
        1. Sven: Sortiere einfach die Spalte der Differenzen aufsteigend, und nimm den ersten Wert. Das ist der kleinste. Parallel kannst du dann auch die ID nehmen.

          Icke: Das ist doch mal ne gute Idee. Danke. Läuft. Sieht dann so aus:

          select ID, wert, from_unixtime(Datum), abs(Datum-unix_timestamp('2006-5-1')) diff from werte order by diff limit 1;

          1. Hallo,

            warum erst eine Berechung der Differenz machen und nicht einfach die Menge beschreiben?

              
            SELECT Id, wert, /* weitere felder */  
            FROM werte  
            WHERE  Datum > @DatumsVariable  
            ORDER BY Datum ASC  
            LIMIT 1;  
            
            

            Angaben ohne Gewehr ;)

            Für @DatumsVariable setze einfach den entsprechend gewünschten Datumswert im korrekten Datentypen ein.

            Cheers,
            Frank

            1. Moin!

              warum erst eine Berechung der Differenz machen und nicht einfach die Menge beschreiben?

              SELECT Id, wert, /* weitere felder */
              FROM werte
              WHERE  Datum > @DatumsVariable
              ORDER BY Datum ASC
              LIMIT 1;

              
              >   
              > Angaben ohne Gewehr ;)  
                
              Du hast die Wirkung von ABS() unterschlagen. Es geht nicht darum, den kleinsten Datumswert, der darüber (oder darunter) liegt, zu finden, sondern den, der am nächsten dran liegt (nach oben oder unten).  
                
               - Sven Rautenberg
              
              -- 
              "Love your nation - respect the others."
              
              1. Ups, sorry, hab ich überlesen, stimmt. Danke für den Hinweis.