MySQL Datenbank die letzten Werte bzw. die Maximalwerte je Tag

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
rpi-joe
User
Beiträge: 23
Registriert: Mittwoch 27. Januar 2021, 15:27

Guten Abend,
seit Tagen probiere ich an einer Lösung rum, aus der MySQL Datenbank die letzten Werte bzw. die Maximalwerte je Tag in den letzten 3 Tagen auszulesen.
Hintergrund ist meine Idee, die Werte unserer Wasseruhr, die ich mit einem Raspberry erfasse (Thread begann unter Netzwerkprogrammierung - SSH Tunnel zum MySQL Server) auf einem 2ten Raspberry mit LCD (16x2) anzuzeigen , z.B.

Gestern: 480 Liter
Heute : 50 Liter

Jetzt habe ich schon viele Möglichkeiten ausprobiert, Tipps aus diesem Forum und von Stackoverflow, aber immer bleiben Fehler.
Mir hat es schon ein paar Mal die MySQL stillgelegt. Deshalb wende ich mich nun an euch um die Bitte, mir den Weg zum Ziel zu zeigen.

Stand jetzt mit Ausgabe der Werte im Terminal:

Code: Alles auswählen

import pymysql
import time

def main():
    # init mySQL
    db = pymysql.connect(
        host='192.168.1.100',
        user='messi',
        password='mess',
        database='smarthome'
    )

    try:
        cursor = db.cursor()
        while True:
            # get data from MySQL
            cursor.execute('SELECT MAX(counter_w) FROM messwerte_wasser WHERE Datum = NOW() - 1 INTERVAL 2 DAY')
            counter_2old = cursor.fetchone()[0]

            cursor.execute('SELECT MAX(counter_w) FROM messwerte_wasser WHERE Datum = NOW() - 1 INTERVAL 1 DAY')
            counter_old = cursor.fetchone()[0]

            cursor.execute('SELECT MAX(counter_w) FROM messwerte_wasser WHERE Datum = NOW()')
            counter_today = cursor.fetchone()[0]

            # Testausgabe
            print(counter_2old)
            print(counter_old)
            print(counter_today)

            # print() für LCD noch erstellen
            # counter_yesterday = counter_old - counter_2old
            # counter = counter_today - counter_old

            time.sleep(5)

    except KeyboardInterrupt:
        pass
    finally:
        cursor.close()
        db.close()

if __name__ == '__main__':
    main()



Vielleicht denke ich nur zu kompliziert ??

Danke für jeden Hinweis
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie sieht denn Dein Datenbankschema aus?
Auch bei Feldnamen in Datenbanken sollte man keine Abkürzungen benutzen, das counter_w sollte wohl irgendwas mit Wasser sein?
Statt drei Abfragen würde man eine machen, wahrscheinlich mit "GROUP BY"
rpi-joe
User
Beiträge: 23
Registriert: Mittwoch 27. Januar 2021, 15:27

@Sirius3: Ahh, sorry.
in der Tabelle messwerte_wasser wird der Zählerstand der Wasseruhr in counter_w abgelegt. Die MySQL macht einen timestamp dazu.
Der counter_w erhöht sich jeweils um 10 und kann nicht niedriger sein als vorausgegangene Messwerte, z.Zt. 511590 -> 511600.
Der Max ist dadurch auch der letzte Wert eines Tages. Ziehe ich davon den Wert des Vortages ab, habe ich den aktuellen Verbrauch.
Mache ich das auch für einen Tag davor, habe ich den Verbrauch von "gestern"!

Leider habe ich immer bei NOW() und CURDATE Fehler, mit Klammern oder ohne, mit Hochkomma oder ohne u.s.w.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@rpi-joe: Möglicherweise denkst du zu kompliziert. Denn mySQL kennt die SQL-typischen Aggregatfunktionen. Reicht dir als Verbrauch die Differenz zwischen dem kleinsten und dem größten Wert eines Tages? Für die aktuellsten 3 Daten wäre das:

Code: Alles auswählen

SELECT date(datum) AS date, min(counter_w) as min, max(counter_w) AS max, (max(counter_w)- min(counter_w)) AS diff
FROM messwerte_wasser
GROUP BY date
ORDER BY date DESC
LIMIT 3;
rpi-joe
User
Beiträge: 23
Registriert: Mittwoch 27. Januar 2021, 15:27

@Sirius3:
Geht es in die Richtung

Code: Alles auswählen

  cursor.execute('SELECT counter_w FROM messwerte_wasser [WHERE Datum = NOW() ] GROUP BY Datum')
  counter_today = cursor.fetchall()[0]
und dann in eine While-Schleife, um mehrere Werte abzufragen, oder macht das MySQL selbst?
Wie gebe ich die Datums Werte für gestern und vorgestern ein?

P.S. Warum kann ich meinen vorigen Beitrag nicht mehr ergänzen?


@sparrow: Habe deinen Beitrag erst hinterher gesehen :-(
Das werde ich einbauen und versuchen, zu verstehen, danke.
Der Verbrauch pro Tag reicht mir, notfalls könnte ich noch 10 draufrechnen, dann stimmt es ganz genau.
rpi-joe
User
Beiträge: 23
Registriert: Mittwoch 27. Januar 2021, 15:27

@sparrow: Vielen Dank für deine Unterstützung :-)

Habe in phpMyAdmin die Zeile eingegeben und erst mal formatieren lassen:

Code: Alles auswählen

SELECT
    DATE(datum) AS DATE,
    MIN(counter_w) AS MIN,
    MAX(counter_w) AS MAX,
    (
        MAX(counter_w) - MIN(counter_w)
    ) AS diff
FROM
    messwerte_wasser
GROUP BY
    DATE
ORDER BY
    DATE
DESC
LIMIT 3
so konnte ich es besser verstehen. Dann habe ich noch die Ausgabe im Terminal angehängt:

Code: Alles auswählen

            for (datum, min, max, diff) in cursor:
                print("{} {} L, {} L, {} L".format(datum, min, max, diff))
Ergebnis sieht gerade so aus:

Code: Alles auswählen

2021-02-12 511760 L, 511790 L, 30 L
2021-02-11 511000 L, 511750 L, 750 L
2021-02-10 510540 L, 510990 L, 450 L
Das werd ich noch für das LCD anpassen und vielleicht noch mit 2 Tastern fürs rauf- und runterscrollen versehen. Dann kann sich jeder durch den Monat scrollen.

Vielen Dank nochmal, hat sehr geholfen.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@rpi-joe: Wenn du scrollen willst: LIMIT kann man in SQL mit einem Parameter aufrufen (Anzahl der Datensätze) oder mit zwei Parametern (Offset, Anzahl der Datensätze). LIMIT 3, 3 gibt dir den 4. 5. und 6. Datensatz; Limit 6, 3 den 7., 8. und 9.
rpi-joe
User
Beiträge: 23
Registriert: Mittwoch 27. Januar 2021, 15:27

@sparrow: Danke für den Tipp, werde mal schauen, wie ich es angehe.
Antworten