If Abfrage aus Daten aus Datenbank

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
linvris
User
Beiträge: 11
Registriert: Montag 17. März 2025, 13:46

Hallo zusammen,
hier mein Programm:

Code: Alles auswählen

#!/usr/bin/env python
import RPi.GPIO as GPIO
from joyit_mfrc522 import SimpleMFRC522
import datetime
import time
import mysql.connector
import os
import board
GPIO.setmode(GPIO.BCM)
my_db = mysql.connector.connect(host = "localhost", user = "ich", passwd = "ich", db = "ich")
reader = SimpleMFRC522()
while True:
    print("Token Anhalten")
    card, text = reader.read()
    print("Token Angehalten")
    now = datetime.datetime.today()
    ad = now.strftime('%Y-%m-%d')
    aj = now.strftime('%Y')
    az = time.strftime('%H:%M:%S', time.localtime())
    print("Token = " + str(card))
    print("Datum = " + ad)
    print("Ist er Token zugeordnet ?")
    time.sleep(2)
    mycursor = my_db.cursor()
    mycursor.execute("SELECT * FROM db WHERE db03 = %s", (card,))
    myresult = mycursor.fetchone()
    if myresult is not None:
        print("Token ist zugeordnet")
        print("Gibt es ein Eintrag in der ISS ?")
        #Bis hier soweit alles ok
        #Es muss die ID ermittelt werden zu einem Eintrag 
        #von Datum (heute) und Leerfeld von vsb07
        #von hier ab, komme ich nicht weiter
        mycursor = my_db.cursor()
        #mycursor.execute("SELECT * FROM erfassung WHERE rfid LIKE card AND datum = ad AND zeit2 = ''")
        mycursor.execute("SELECT * FROM erfassung WHERE rfid LIKE %s", (card,))
        myresult = mycursor.fetchall()
        for x in myresult:
            x0 = x[0]
            x1 = x[1]
            x2 = x[2]
            x3 = x[3]
            x4 = x[4]
            print(x)
das Ergebnis:

Code: Alles auswählen

(1, '500402455868', datetime.date(2025, 11, 1), '12-45-28', '16-45-28')
(2, '500402455868', datetime.date(2025, 11, 4), '15:37:54', '16:37:54')
(3, '500402455868', datetime.date(2025, 11, 4), '16:39:47', '')
(4, '500402455868', datetime.date(2025, 11, 5), '10:39:47', '')
(5, '500402455868', datetime.date(2025, 11, 6), '08:39:47', '')
(6, '500402455868', datetime.date(2025, 11, 7), '08:39:47', '')
(7, '500402455868', datetime.date(2025, 11, 8), '16:39:47', '')
(8, '500402455868', datetime.date(2025, 11, 9), '10:39:47', '')
(9, '500402455868', datetime.date(2025, 11, 10), '08:39:47', '')
(10, '500402455868', datetime.date(2025, 11, 11), '08:39:47', '')
per IF möchte ich folgendes Abfragen,
wenn Feld "x2" aktuellen Datum und "x4" leer ist zeige mir "x0"
sonst zeige mir lade akku

Code: Alles auswählen

if x2 == ad and x4 == "":
    print("Zeige mir x0")
else:
    print("lade Akku")
meine aktuelles Datum sieht so aus 2025-11-06
phpmyadmin zeit mein Datum so an 2025-11-06
in der Ausgabe von python wieder anders (siehe oben), wie muß ich nun meine IF Abfrage aufbauen damit es klappt ?
Benutzeravatar
grubenfox
User
Beiträge: 628
Registriert: Freitag 2. Dezember 2022, 15:49

Vermutlich entweder

Code: Alles auswählen

now = datetime.date.today()
und

Code: Alles auswählen

if x2 == now and x4 == "":
oder (wenn now unverändert bleibt)

Code: Alles auswählen

if x2.strftime('%Y-%m-%d') == ad and x4 == "":
Sirius3
User
Beiträge: 18322
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutze sprechende Namen, was soll `ad` `adj` oder `az` bedeuten. Wenn man das Datum abfragt, immer in einer Abfrage machen und nicht Datum und Zeit unabhängig.
Warum wird der Nutzer künstlich 2 Sekunden lang ausgebremst?
Ich weiß, dass es mysql heißt, deshalb muß aber ein Cursor nicht mycursor heißen.
Auch Tabellen sollten sprechende Namen haben, `db` ist schlecht, `db03` noch schlechter.
Warum ein `select *` wenn Du keine der zurückgegebenen Spalten benutzt?
*-SELECTS sollte man niemals benutzen, weil sich dann die Reihenfolge der Spalten nie ändern darf. x und x0 bis x4 sind natürlich ganz katastrophal, weil niemand weiß, was denn nun x3 ist.
Es gibt Tuple-Unpacking.

Code: Alles auswählen

reader = SimpleMFRC522()
while True:
    print("Token Anhalten")
    card, text = reader.read()
    print("Token Angehalten")
    now = datetime.datetime.now()
    print("Token = ", card)
    print("Datum = ", f"{now:%y-%m-%d}")
    print("Ist er Token zugeordnet ?")
    time.sleep(2)
    with my_db.cursor() as cursor:
        cursor.execute("SELECT db03 FROM db WHERE db03 = %s", (card,))
        if cursor.fetchone():
            print("Token ist zugeordnet")
            print("Gibt es ein Eintrag in der ISS ?")
            cursor.execute("SELECT id, rfid, date, time_in, time_out FROM erfassung WHERE rfid LIKE %s", (card,))
            results = cursor.fetchall()
            for _id, rfid, date, time_in, time_out in results:
                print(_id, rfid, date, time_in, time_out)
Nun gibt es hier einige grundlegende Probleme mit der Datenbank: Datum und Uhrzeit sollten immer als TIMESTAMP (bzw. TIMESTAMP WITH TIMEZONE) in einer Spalte gespeichert werden, niemals als Text, und niemals getrennt. Wenn das wirkliche Daten sieht, siehst Du ja schon das Problem, dass irgendwer die Zeit in einer falschen Formatierung gespeichert hat.
Beim Datum kommt ja schon korrekterweise kein String, sondern ein datetime.date-Objekt zurück. Und das versteht die Datenbank auch, damit kann man dann einfach vergleichen mit "where DATE(date_in) >= DATE(%s)".
linvris
User
Beiträge: 11
Registriert: Montag 17. März 2025, 13:46

Antwort zu fragen:
ad = aktuelles datum, aj = aktuelles jahr az = aktuelle zeit
die 2 sekunden pause ist für eine LCD anzeige und zum lesen für print
die namen schon vorhanden sind habe ich übernommen worauf es ankommt habe ich verständliche namen genommen.

der gezeigte Code von bringt fehler also wieder zurück

print(x2.strftime('%Y-%m-%d')) = 2025-11-06
print(ad) = 2025-11-06
der fehler muß in der if abfrage liegen
ich bekomme:

Code: Alles auswählen

Token Anhalten
Token Angehalten
Token = 500402455868
Datum = 2025-11-06
Ist er Token zugeordnet ?
Token ist zugeordnet
Gibt es ein Eintrag in der ISS ?
2025-11-06
1
KO
Eintrag zum kommen
2
KO
Eintrag zum kommen
3
KO
Eintrag zum kommen
4
KO
Eintrag zum kommen
OK
5
Nachtrag zum gehen
6
KO
Eintrag zum kommen
7
KO
Eintrag zum kommen
8
KO
Eintrag zum kommen
9
KO
Eintrag zum kommen
10
KO
Eintrag zum kommen
Token Anhalten
ales was nach 1 kommt ist zuviel
ich möchte nur eine Zahl sehen welche zu Kriterien passt:
z.B.
DB Eintrag
(5, '500402455868', '2025-11-06', '08:39:47', ''),
soll nur die 5 ( print(x0) ) angezeigt werden
Sirius3
User
Beiträge: 18322
Registriert: Sonntag 21. Oktober 2012, 17:20

Und welche Änderungen hast Du jetzt gemacht?
Ist die Datenbank angepasst? Hast Du die Namen verbessert? Hast Du die Abfrage erweitert?
Deine Ausgabe passt nicht zum ursprünglichen Code.
Benutzeravatar
__blackjack__
User
Beiträge: 14220
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Randbemerkung: Ich würde `card` explizit in eine Zeichenkette umwandeln und mich nicht darauf verlassen, dass das die Datenbankanbindung schon machen wird. Alternativ könnte man auch schauen, ob die Datenbank nicht einen Zahltyp hat, der gross genug ist diese Werte aufzunehmen. Könnte Platz und Rechenzeit sparen.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
linvris
User
Beiträge: 11
Registriert: Montag 17. März 2025, 13:46

Mein kompletter Code mit meinen Zielen

Code: Alles auswählen

#!/usr/bin/env python
import RPi.GPIO as GPIO
from joyit_mfrc522 import SimpleMFRC522
import datetime
import time
import mysql.connector
import os
import board
GPIO.setmode(GPIO.BCM)
my_db = mysql.connector.connect(host = "localhost", user = "ich", passwd = "ich", db = "ich")
reader = SimpleMFRC522()
while True:
    print("Token Anhalten")
    card, text = reader.read()
    print("Token Angehalten")
    now = datetime.datetime.today()
    ad = now.strftime('%Y-%m-%d')
    aj = now.strftime('%Y')
    az = time.strftime('%H:%M:%S', time.localtime())
    time.sleep(2)
    mycursor = my_db.cursor()
    mycursor.execute("SELECT * FROM user WHERE rfid = %s", (card,))
    myresult = mycursor.fetchone()
    if myresult is not None:
        mycursor = my_db.cursor()
        mycursor.execute("SELECT * FROM erfassung WHERE rfid LIKE %s", (card,))
        myresult = mycursor.fetchall()
        for x in myresult:
            x0 = x[0]
            x1 = x[1]
            x2 = x[2]
            x3 = x[3]
            x4 = x[4]
            #hier muss; die ID ermittelt werden von Datum, RFID und ZEIT2 ( Zeit2 ohne Eintrag )
            if x2.strftime('%Y-%m-%d') == ad:
                print(x0)
                print("Es wurde 2te Zeit eingetragen")
                #hier muss 2te Zeit nachgetragen werden zu gesuchten Eintrag
                #Print ist nur was passeiren soll, den eintrag Code habe ich 
            else:
                print(x0)
                print("Es wird 1te Zeit sowie Datum und User Daten eingetragen")
                #hier muss mit Datum und 1te Zeit eingetragen werden
                #Print ist nur was passeiren soll, den eintrag Code habe ich
        time.sleep(0.2)
    else:
        mycurser = my_db.cursor()
        mycurser.execute("SELECT * FROM rfid WHERE rfid = %s", (card,))
        myresult = mycurser.fetchone()
        if myresult is not None:
            print("Token ist vorhanden")
            #Print ist nur was passeiren soll, den eintrag Code habe ich fuer Ausgabe von Fehler in Optisch und Akustisch 
        else:
            print("Token wird eingetragen")
            #Print ist nur was passeiren soll, den eintrag Code habe ich
        time.sleep(0.2)

#CREATE TABLE IF NOT EXISTS `user` (
#  `id` int(255) UNSIGNED NOT NULL AUTO_INCREMENT,
#  `vorname` varchar(50) NOT NULL,
#  `nachname` varchar(50) NOT NULL,
#  `rfid` varchar(20) NOT NULL,
#  PRIMARY KEY (`id`)
#) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci ROW_FORMAT=COMPACT;,
#INSERT INTO `user` (`id`, `vorname`, `nachname`, `rfid`) VALUES
#(1, '0', '0', '500402455868'),
#(2, '1', '1', '1060436786393');
#CREATE TABLE IF NOT EXISTS `erfassung` (
#  `id` int(255) UNSIGNED NOT NULL AUTO_INCREMENT,
#  `rfid` varchar(50) NOT NULL,
#  `datum` date NOT NULL,
#  `zeit1` varchar(8) NOT NULL,
#  `zeit2` varchar(8) NOT NULL,
#  PRIMARY KEY (`id`)
#) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci ROW_FORMAT=COMPACT;,
#INSERT INTO `erfassung` (`id`, `rfid`, `datum`, `zeit1`, `zeit2`) VALUES
#(1, '500402455868', '2025-11-01', '12-45-28', '16-45-28'),
#(2, '500402455868', '2025-11-04', '15:37:54', '16:37:54'),
#(3, '500402455868', '2025-11-04', '16:39:47', ''),
#(4, '500402455868', '2025-11-05', '10:39:47', ''),
#(5, '500402455868', '2025-11-06', '08:39:47', ''),
#(6, '500402455868', '2025-11-07', '08:39:47', ''),
#(7, '500402455868', '2025-11-08', '16:39:47', ''),
#(8, '500402455868', '2025-11-09', '10:39:47', ''),
#(9, '500402455868', '2025-11-10', '08:39:47', ''),
#(10, '500402455868', '2025-11-11', '08:39:47', ''),
#(11, '1060436786393', '2025-11-06', '08:39:47', '');
#CREATE TABLE IF NOT EXISTS `rfid` (
#  `id` int(255) UNSIGNED NOT NULL AUTO_INCREMENT,
#  `rfid` varchar(50) NOT NULL,
#  PRIMARY KEY (`id`)
#) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci ROW_FORMAT=COMPACT;
#INSERT INTO `rfid` (`id`, `rfid`) VALUES
#(1, '21008674176186');
#In RFID sind nur Token wo nicht in USER eingetragen sind
ich brauche nur die ID ( die ID für die wo Datum und 2te Zeit fehlt ) als aus in der IF Abfrage für die 2te Zeit eingabe.
Wenn ich den Code richtte verstanden hatte oder denke dann soll in der IF Abfrage nur eine ID gezeigt werden.
Aber ich bekomme da alle angezeit und versteh nun die Abfrage nicht.
Benutzeravatar
noisefloor
User
Beiträge: 4238
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

das Datenbankdesign ist ziemlich kaputt... Wenn du eine Tabelle mit allen (gültigen) RFID hast, dann kann a) die RFID Kennung der Primärschlüssel sein, weil es jede RFID Kennung nur 1x geben darf und b) ist USER zu RFID eine 1:1 Beziehung (oder 1:n, wenn RFID an andere Nutzer weitergeben werden, wenn ein Nutzer ausscheidet). Also solltest du in der Tabelle USER mit einem Fremdschlüssel arbeiten. Was ist denn "Zeit 1" und "Zeit 2"? Kommen und Gehen? Dann fehlt die Logik die feststellt, ob ein Auslesen des RFID Chips ein "Kommen" oder "Gehen" Vorgang ist und die Logik, wann "Zeit 2" zu "Zeit 1" gehört. Bessere wäre auch, in der Tabelle "Erfassung" nur Nutzer und _eine_ Zeit zu speichern und den Rest wie Zeit zwischen zwei aufeinanderfolgenden Ergebnisse für einen Nutzer programmseitig auszuwerten.

Die Frage "ich brauche nur die ID" verstehe ich nicht - wenn du nur einen Wert aus einer Tabelle brauchst -> dann frag' nur einen ab, also _keine_ `SELECT * ` Abfrage. Und du solltest dringend die bereits gegebenen Hinweis zum Code, Variablenname etc in deinen Code einarbeiten.

Gruß, noisefloor
Benutzeravatar
__blackjack__
User
Beiträge: 14220
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@linvris: Da sind ja immer noch die gleichen Fehler und schlechten Namen und der problematische Datenbankentwurf drin. Warum gehst Du das nicht an? Es macht nicht so wirklich Sinn damit weiter zu machen wenn man den Code den man jetzt in diesem Zustand dazu schreibt, dann doch wieder ändern muss.

Bei der Erfassung sollte es nicht `datum` und `zeit1` und `zeit2` geben, sondern zwei TIMESTAMP-Werte. Wobei der zweite „nullable“ ist. Das momentan `zeit2` NOT NULL ist, aber statt einer Zeitangabe auch eine leere Zeichenkette enthalten kann, ist doch Unsinn, denn die leere Zeichenkette bedeutet ja es gibt den Wert noch nicht. Genau dafür gibt es doch NULL. Und genau danach kann man dann suchen: den einzigen Datensatz für das entsprechende Token der NULL als Endzeitpunkt hat. Davon darf es nämlich zu jedem Zeitpunkt nur genau einen geben, sonst stimmt etwas nicht. Wobei man sich auch überlegen muss, wie man mit diesem Fall umgeht. Oder man sucht den jüngsten Datensatz mit NULL für den zweiten Zeitpunkt.

Das `rfid` in drei Tabellen gespeichert wird und mal 20 und mal 50 Zeichen lang sein darf ist auch schräg.
“Ich bin für die Todesstrafe. Wer schreckliche Dinge getan hat, muss eine angemessene Strafe bekommen. So lernt er seine Lektion für das nächste Mal.” — Britney Spears, Interview in der französischen Zeitung Libération, 2. April 2002
linvris
User
Beiträge: 11
Registriert: Montag 17. März 2025, 13:46

Meine tabellen haben weitere einträge wo aber für tests nicht notwendig sind und nur für statistik relevant ist, aus dem Grund habe ich sie nicht im testaufbau.
ich habe nie programieren gelernt auch nicht sql sondern alles nur zusammen gesucht und geschaut was verstehe ich
daten wo existieren und am laufen sind werde ich nicht umstellen, was auch nicht meine aufgabe ist .
wie in tabelle zu sehen von user habe ich nur 2 einträge aber es ist nur test und am ende geht es über 1200 user
ich habe alles reduziert für test
es gibt ein php programm " small time " aber das ist mir zum umfangreich und in php gehalten ich wollte es abgespeckt in python um nicht zu viele sachen zu haben (je mehr sachen je mehr fehler quellen)
all das löst nicht das problem mit der Abfrage
beim ersten anhalten wird datum und zeit1 sowie rfid und user gespeichert ( wie bei arbeitsbegin )
beim zweiten anhalten soll 2te zeit dazu geschrieben werden.
später werde ich mit ein klick eine ausgabe setzen je nach user, aus diesem grund habe ich alle wichtigen daten in einer tabelle gepackt
ich denke ich werde das ganze verlagern nach php dort klappen meine abfragen
danke
Benutzeravatar
noisefloor
User
Beiträge: 4238
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

linvris hat geschrieben: Freitag 7. November 2025, 18:15 ich denke ich werde das ganze verlagern nach php dort klappen meine abfragen
Gut. Wobei die Problem mit der Abfrage eigentlich rein gar nichts mit der Programmiersprache $FOO zu tun haben. SQL ist in PHP genau so SQL wie in Python.

Und was oben zum kaputten Datenbankdesign gesagt wurde und zum Prinzip der Abfrage gilt weiterhin, egal ob PHP oder Python oder ...
ich habe nie programieren gelernt auch nicht sql sondern alles nur zusammen gesucht und geschaut was verstehe ich
.
Na ja, wenn man Programmieren nie gelernt hat - egal ob als Hobby oder beruflich - dann kann man halt nicht programmieren. Wenn man Schwimmen nicht gelernt hat kann man halt nicht schwimmen. Wenn man es trotzdem machen will -> lernen. Der Unterschied ist: beim Schwimmen merkt man es ziemlich schnell, ob es klappt oder nicht. Beim Programmieren kann man es u.U. erst merken, wenn es deutlich zu spät ist... Wenn du wirklich mal > 1000 Nutzer verwalten willst, dann solltest du dringend lernen und besser werden. Der obige Ansatz fliegt dir sicher irgendwann hart um die Ohren.

Wenn's dir mit PHP oder einer anderen Sprache leichter fällt -> go for it. Es zwingt dich ja (hoffentlich) keiner, Python zu nutzen.

Gruß, noisefloor
Antworten