Nachkommastelle nach Kalkulation mit LAG-Funktion

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    Nachkommastelle nach Kalkulation mit LAG-Funktion

    Hallo,

    ich hatte heute einige Beiträge hier gelesen und dabei fiel mir ein altes Problem, für das ich noch keine Lösung fand, wieder ein.

    Ich trage in eine MySQL-DB die Zählerstande mehrerer Energiezähler ein. Die Tabelle hat einen Timestamp und den Zählerstand (leider als VARCHAR).
    Nun möchte ich eine 3. Spalte hinzufügen, die die Differenz zum vorherigen Eintrag anzeigt.
    Das klappt mit nachstehendem Befehl schon mal ganz gut, nur leider habe ich in meiner 3. Spalte keine Nachkommastellen.

    Kann mir jemand sagen, wie ich die Nachkommastellen anzeigen lassen kann?

    SQL-Abfrage

    1. SELECT DATE_FORMAT(Zeitstempel,'%Y-%m-%d %H:%i') as Zeitstempel, CAST(replace(Zaehlerstand, ',', '.') AS DECIMAL(11,3)) as Zählerstand, Zaehlerstand - LAG(Zaehlerstand, 1) over() as Delta FROM energiedaten.test WHERE
    2. (Zeitstempel BETWEEN '2024-01-01 00:00' AND '2024-01-01 00:01') OR
    3. (Zeitstempel BETWEEN '2024-02-01 00:00' AND '2024-02-01 00:01') OR
    4. (Zeitstempel BETWEEN '2024-03-01 00:00' AND '2024-03-01 00:01') OR
    5. (Zeitstempel BETWEEN '2024-04-01 00:00' AND '2024-04-01 00:01') OR
    6. (Zeitstempel BETWEEN '2024-05-01 00:00' AND '2024-05-01 00:01') OR
    7. (Zeitstempel BETWEEN '2024-06-01 00:00' AND '2024-06-01 00:01') OR
    8. (Zeitstempel BETWEEN '2024-07-01 00:00' AND '2024-07-01 00:01') OR
    9. (Zeitstempel BETWEEN '2024-08-01 00:00' AND '2024-08-01 00:01') OR
    10. (Zeitstempel BETWEEN '2024-09-01 00:00' AND '2024-09-01 00:01') OR
    11. (Zeitstempel BETWEEN '2024-10-01 00:00' AND '2024-10-01 00:01') OR
    12. (Zeitstempel BETWEEN '2024-11-01 00:00' AND '2024-11-01 00:01') OR
    13. (Zeitstempel BETWEEN '2024-12-01 00:00' AND '2024-12-01 00:01');
    Nachkommastellen hast du (vermutlich) nicht, weil du in der Definition von Delta nicht castest. Dass der das überhaupt durchwinkt... MySQL halt

    Deine Query ist gar nicht schön, was machst du wenn du 2023 auch sehen willst? Welche Werte kann Zeitstempel denn haben? Ist das auch ein VARCHAR?
    Ich denke da kann man einiges ändern

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Das war erstmal nur ein Provisorium für 2024, da habe ich noch keine Variablen reingepackt.
    Der Zeitstempel ist ein Timestamp(0).

    Wie würdest du es lösen? Also abgesehen von der Variabilität?

    Wenn ich es wie folgt ändere, dann sind die Nachkommastellen immer 0...
    Ich würde ja *1000 und später wieder /1000 rechnen, aber irgendwie kriege ich das nicht rein, ohne Syntaxfehler.

    SQL-Abfrage

    1. SELECT DATE_FORMAT(Zeitstempel,'%Y-%m-%d %H:%i') as Zeitstempel, CAST(replace(Zaehlerstand, ',', '.') AS DECIMAL(11,3)) as Zählerstand, cast(Zaehlerstand - LAG(Zaehlerstand, 1) over(order by Zeitstempel) as decimal(11,3)) as Delta FROM energiedaten.test WHERE


    Ich bin nur blutiger Anfänger im Themengebiet SQL. :D

    2024-01-01 00:00
    537.940
    NULL
    2024-02-01 00:00
    554.039
    17.000
    2024-03-01 00:00
    571.112
    17.000
    2024-04-01 00:00
    585.717
    14.000
    2024-05-01 00:00
    599.273
    14.000
    2024-06-01 00:00
    611.382
    12.000

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Murdersquad“ ()

    Ach * 1000 lässt der nicht zu? Sehr interessant, die Wege des MySql sind unergründlich.
    Schau dir mal Zählerstand an. Da Castest du Zaehlerstand direkt. Das gibt dir eine Zahl.
    In Delta machst du eine Rechnung, da castest du erst das Ergebnis, von dem ich nicht weiß wie es zustandekommt oder was es ist, denn VARCHAR - VARCHAR sollte genauso scheitern wie VARCHAR * 1000
    Stattdessen nimmst du den Ausdruck CAST(replace(Zaehlerstand,',','.') as Decimal(11,3)) und ersetzt Zaehlerstand in Delta damit.

    Aber hast du auch mal die Methode aus dem anderen Beitrag ausprobiert? Geht die nicht?

    SQL-Abfrage

    1. Select Cast(Zeitstempel, Date) as Zeitstempel,
    2. Min(CAST(replace(Zaehlerstand,',','.') as Decimal(11,3))) as MonatsStart,
    3. Max(Cast(replace(Zaehlerstand,',','.') as Decimal(11,3))) - Min(Cast(replace(Zaehlerstand,',','.') as Decimal(11,3))) as Delta
    4. From energiedaten.test
    5. Group By Cast(Zeitstempel, Date)

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Du hast vollkommen Recht.
    Ich hatte nicht mehr daran gedacht, dass da ja noch die VARCHAR-Variable im Hintergrund steht...

    So haut es im Test erstmal die richtigen Ergebnisse raus:

    SQL-Abfrage

    1. SELECT DATE_FORMAT(Zeitstempel,'%Y-%m-%d %H:%i') as Zeitstempel, CAST(replace(Zaehlerstand, ',', '.') AS DECIMAL(11,3)) as Zählerstand, CAST(CAST(replace(Zaehlerstand, ',', '.') AS DECIMAL(11,3)) - LAG(CAST(replace(Zaehlerstand, ',', '.') AS DECIMAL(11,3)), 1) over(order by Zeitstempel) as decimal(11,3)) as Delta FROM energiedaten.test WHERE


    Jetzt kann ich es auch mal aufhübschen.

    PS: Die Methode aus dem anderen Beitrag funktioniert bei mir nicht, da ich eine etwas andere Anforderung habe. Ich möchte nicht den Min-Max-Stand ermitteln, sondern den Stand immer zum ersten des Monats um 00:00 Uhr.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Murdersquad“ ()

    Murdersquad schrieb:

    PS: Die Methode aus dem anderen Beitrag funktioniert bei mir nicht, da ich eine etwas andere Anforderung habe. Ich möchte nicht den Min-Max-Stand ermitteln, sondern den Stand immer zum ersten des Monats um 00:00 Uhr.
    Das macht dein Sql aber ganz und gar nicht, du meinst wohl die Differenz der Stände der Ersten der Monate

    Ist der Zaehlerstand bei dir nicht monoton steigend über die Zeit?
    Dann verstehe ich warum max min nicht hinhaut.

    Falls der doch monoton steigend ist:
    Hast du es trotzdem ausprobiert? Welche Unterschiede stellst du fest? In diesem Fall sollte der Max-Wert von Monat 1 = dem Min-Wert von Monat 2 sein.
    Allenfalls wenn der Sprung zwischen den Mess-Intervallen zu groß ist, ist da ein Unterschied.
    Lässt sich aber auch beheben, nur ist das wirklich notwendig?

    Ich hoffe dein MySql unterstützt schon Common Table Expressions, sonst wird es sehr unleserlich

    SQL-Abfrage

    1. With castedValues as (
    2. Select Cast(Zeitstempel as date) as truncDat, Cast(replace(Zaehlerstand,',','.') as decimal(11,3)) as decimalStand
    3. From energiedaten.test)
    4. Select truncDat as Zeitstempel, Min(decimalStand) as MonatStart, Min(decimalStand) - Lag(Min(decimalStand), 1, 0) OVER(Order By truncDat) as Delta
    5. From castedValues
    6. Group By truncDat

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Neu

    Ja, er ist monoton steigend.
    Dein Script ist natürlich besser. Ich habe jetzt mal mit Group by MONTH(truncDat) gearbeitet, aber er listet mir dann nicht alles auf, da muss ich nochmal nachschauen. Er bricht im März ab, aber mit der Uhrzeitumstellung sollte es nichts zu tun haben.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Murdersquad“ ()

    Neu

    Ach ja stimmt, habe jeden Tag statt jeden Monat gruppiert. Ich hätte den Month im With Block definiert und zudem das Jahr mit reingebastelt, sonst gruppiert er verschiedene Jahre in einen Monat.
    Mach sonst am besten ein fiddle fertig, wenn du irgendwelche Sonderfälle findest.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()