ibvfblel: SELECT Datensatz mit Datumsbereich

Hallo,

ich bekomme jeden Tag in meine MSSQL Datenbank etliche Werte von Maschinen eingetragen. Beispielsweise jede 3 Stunden. Wenn aber eine Maschine ausfällt erhalte ich von dem Tag keine Daten, was nicht tragisch ist.

Wenn ich nun aber eine Abfrage mache und die Werte von einem bestimmten Datum ausgeben möchte, dann ist die eine Maschine nicht vorhanden (was ja korrekt ist). Nun möchte ich aber, dass ich die letzten bekannten Werte erhalte (auch wenn es zwei Tage alt ist) und nicht den genauen angegeben Wert meines Datums.

Wie mache ich das?

Danke

  1. order by datum desc limit 10

    1. dann habe ich aber die letzten 10 Werte von unterschiedlichen Datum. Ich habe in der SELECT Anweisung ein Datum angegeben, möchte nur diese Werte von dem Tag AUSSER er hat keinen Wert, dann soll er einen Tag zurück gehen, wenn er dort auch ncihts hat, nochmals einen tag zurück usw...

      order by datum desc limit 10

      1. Tach!

        Ich habe in der SELECT Anweisung ein Datum angegeben, möchte nur diese Werte von dem Tag AUSSER er hat keinen Wert, dann soll er einen Tag zurück gehen, wenn er dort auch ncihts hat, nochmals einen tag zurück usw...

        Vielleicht bekommt man das mit einer komplexen Query hin. Aber das wird am Ende umständlicher, als wenn du eine Stored Procedure nimmst. Da kannst du in Code das formulieren, was du eben in Worten formuliert hast, und du hast dazu mehr programmiertechnische Werkzeuge zur Verfügung.

        dedlfix.

        1. da bin ich dann schon überfordert... :-(

          Tach!

          Ich habe in der SELECT Anweisung ein Datum angegeben, möchte nur diese Werte von dem Tag AUSSER er hat keinen Wert, dann soll er einen Tag zurück gehen, wenn er dort auch ncihts hat, nochmals einen tag zurück usw...

          Vielleicht bekommt man das mit einer komplexen Query hin. Aber das wird am Ende umständlicher, als wenn du eine Stored Procedure nimmst. Da kannst du in Code das formulieren, was du eben in Worten formuliert hast, und du hast dazu mehr programmiertechnische Werkzeuge zur Verfügung.

          dedlfix.

          1. könnte man nicht sagen,

            WENN Datum != 1.11.2016 THEN 31.10.2016 ?

            da bin ich dann schon überfordert... :-(

            Tach!

            Ich habe in der SELECT Anweisung ein Datum angegeben, möchte nur diese Werte von dem Tag AUSSER er hat keinen Wert, dann soll er einen Tag zurück gehen, wenn er dort auch ncihts hat, nochmals einen tag zurück usw...

            Vielleicht bekommt man das mit einer komplexen Query hin. Aber das wird am Ende umständlicher, als wenn du eine Stored Procedure nimmst. Da kannst du in Code das formulieren, was du eben in Worten formuliert hast, und du hast dazu mehr programmiertechnische Werkzeuge zur Verfügung.

            dedlfix.

            1. Tach!

              könnte man nicht sagen,

              WENN Datum != 1.11.2016 THEN 31.10.2016 ?

              An welcher Stelle willst du das sagen können?

              So ein DBMS arbeitet mengenorientiert. Du kannst da nicht in IFs und Schleifen denken, um Lösungen zu finden, sondern du muss Bedingungen definieren, was in der Menge enthalten sein soll. Du willst, wenn die Menge der Datensätze von heute leer ist (sprich: COUNT(*) = 0), andere Datensätze haben. Man kann das, denke ich, über UNION machen. Die erste Query liefert Daten mit Datum von heute, die andere liefert Daten von gestern, wenn die Menge von heute leer ist. Die erste Query ist ziemlich geradeaus. Sie liefert entweder etwas oder nichts. Der Trick muss in der zweiten Menge zur Anwendung kommen. Die muss Datensätze liefern, deren Datum von gestern ist und wenn eine Subquery mit Count(*) = 0 liefert für Datensätze mit Datum von heute.

              Bei MySQL würde ich die Subquery separat ausführen, deren Ergebnis in einer nutzerdefinierten Variable ablegen und die statt der Subquery im zweiten Teil verwenden. MSSQL hat sicher auch Variablen, aber das weiß ich nicht.

              Obenstehendes Konstrukt kann man auch noch über ein weiteres UNION mit einer Abfrage mit Datum von vorgestern erweitern. Aber dann weitergehen zu wollen, bis mal ein Tag mit Daten kommt, endet in einem unwartbaren Gebilde. Dann wäre wirklich mal Zeit, sich mit Stored Procedures zu befassen, oder diese Logik in die abfragende Umgebung zu legen.

              dedlfix.

              1. ich bin gerade am überlegen ob ich es nicht so mache, dass ich ein Datumsbereich angebe (bspw. 20.10.-1.11. und in diesem Zeitraum soll er den MAX Wert nehmen. Ich glaube das ist das einfachste oder?

                [Vollzitat entfernt]

          2. Hallo

            Stored Procedure

            da bin ich dann schon überfordert... :-(

            Eine Stored Procedure ist ein in SQL-Code geschriebenes Programm. Es wird auf dem SQL-Server gespeichert, ist ihm also bekannt, und kann wie ein Query von außen aufgerufen werden (EXECUTE dbo.MyProcedure, auch mit Übergabe von Parametern EXECUTE dbo.MyProcedure @param1 = 1, @param2 = 15).

            Wenn du einen MSSQL-Server betreibst, benutzt du dann das „MS SQL Server Management Studio“ zur Verwaltung der Datenbank (Anlegen von Tabellen, Views, etc.)? Dort kannst du eine Prozedur im Editor anlegen und durch einen einmaligen Durchlauf dem Server bekannt machen. Wie, das hängt von deiner Version des Servers und des Management Studios ab. MS verändert leider immer wieder von Version zu Version erheblich die Bedienung, was zu Suchorgien ausarten kann.

            Tschö, Auge

            --
            Wo wir Mängel selbst aufdecken, kann sich kein Gegner einnisten.
            Wolfgang Schneidewind *prust*
  2. Geht alles mit nackigem SQL. Ich nehme mal an, dass deine Tabelle irgendwie so aussieht:

       Maschine        int
       Meldezeit       datetime
       Wert1           int
       Wert2           int
       Wert3           int
    

    Dann liefert dir diese Query das höchste bekannte Datum, zu dem eine Maschine gemeldet hat:

    SELECT Maschine, CAST(MAX(Meldezeit) as DATE) as MaxDate
    FROM Meldungen
    GROUP BY Maschine
    

    Diese Query kannst Du als Subquery verwenden und mit deiner Tabelle Joinen:

    SELECT m.Maschine, m.Meldezeit, m.Wert1, m.Wert2, m.Wert3
    FROM   Meldungen m 
           JOIN (SELECT Maschine, CAST(MAX(Meldezeit) as DATE) as MaxDate
                 FROM Meldungen
                 GROUP BY Maschine) r
           ON m.Maschine = r.Maschine AND CAST(m.Meldezeit as DATE) = r.MaxDate
    

    Ergebnis: Zu jeder Maschine bekommst Du die Meldungen zum letzten bekannten Tag. Das kannst Du jetzt noch mit ORDER BY und werweißwasnoch nach Belieben pimpen.

    Rolf

    1. ich will ja nicht den MAX Wert. Ich möchte ein bestimmtes Datum (was auch in der Vergangenheit liegen kann), und wenn es das nicht gibt, dann nehme die Werte einen Tag zuvor usw...

      [Vollzitat entfernt]

      1. Hallo ibfvblel,

        ich will ja nicht den MAX Wert. Ich möchte ein bestimmtes Datum (was auch in der Vergangenheit liegen kann), und wenn es das nicht gibt, dann nehme die Werte einen Tag zuvor usw...

        Dann musst du eben zuallererst alle Datensätze auswählen, die nicht nach dem bestimmten Datum liegen.

        Bis demnächst
        Matthias

        --
        Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
      2. Entschuldige bitte, dass ich deine Anforderung ungenau gelesen und dann noch deine SQL Grundkenntnisse überschätzt habe.

        Für den 01.11.2016 machst Du es so.

        SELECT m.Maschine, m.Meldezeit, m.Wert1, m.Wert2, m.Wert3
        FROM   Meldungen m 
               JOIN (SELECT Maschine, CAST(MAX(Meldezeit) as DATE) as MaxDate
                     FROM Meldungen
                     WHERE CAST(Meldezeit  AS DATE) <= '2011-11-01'
                     GROUP BY Maschine) r
               ON m.Maschine = r.Maschine AND CAST(m.Meldezeit as DATE) = r.MaxDate
        

        Du kannst Dir den CAST() in der Where-Bedingung sparen, wenn Du sie mit "<" statt "<=" formulierst:

        WHERE Meldezeit < '2016-11-02'
        

        aber um den Preis, dass Du vorher einen Tag aufs Vergleichsdatum aufaddieren musst.

        Du kannst diesen Tag auch vom SQL Server addieren lassen:

        WHERE Meldezeit < DATEADD(DAY, 1, '2016-11-01'
        

        dann hast Du das gewünschte Datum klar in der Query stehen.

        Was davon jetzt die "richtigste" Lösung ist, hängt auch davon ab, wie Du die Query nutzt. Ist sie in ein Programm eingebettet?

        Rolf

        1. Danke

          [Vollzitat entfernt]