Ausgabe nur des letzen Eintrages bei Mehrfacheingabe

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Loewe310
User
Beiträge: 4
Registriert: Montag 5. November 2018, 09:18

Guten Tag und vielen Dank fürs durchlesen,

ich habe mir vorgenommen, eine Zeiterfassung zu erstellen und bin jetzt an folgendem Stand.
Ich kann über RFID-RC522 einen Chip auslesen und sowohl die Chipnummer als auch Datum und Uhrzeit der Erfassung in einer Datenbank speichern. 30 RFID sind geplant
Die Datenbank sehe ich über phpMyadmin.
Da die gleichen rfid mehrfach verwendet werden(es ändert sich nur Uhrzeit und datum), möchte ich in der Datenbank die Spalte rfid von oben nach unten auslesen und nur die letzte Zeile in der die rfid gefunden wird ausgeben.
in der Datenbank namens februar sind die Spalten id, name, rfid, date, time, login, logout vorhanden.
Ziel des ganzen ist es, beim erneuten scannen des Transponders zu erkennen, ob der davorliegende scan ein login oder logout war, um beim erneuten scan genau das gegenteil zu erzielen.
Für die Ausgabe der Abfrage reicht quasi das Ergebnis ob es login oder logout war. das brauch ich dann für die Weiterverarbeitung.

Kurz zu mir: Ich beschäftige mich erst kurz mit Python, Datenbanken und Co.
Ich hoffe es hat jemand lust mir zu helfen und kann mir einen Tip geben.
Ich habe etliches probiert und versucht umzusetzen....aber jetzt komme ich nicht weiter.
Das ist der Stand.

Auszug (hab das ganze auslesen des Transponders weg gelassen)

if status == MIFAREReader.MI_OK:

# Print UID
card_id = str(uid[0])+str(uid[1])+str(uid[2])+str(uid[3])
date = time.strftime("%Y.%m.%d")
time1 = time.strftime("%H:%M:%S")
#date1 = time.strftime("%d.%m.%Y %H:%M:%S")
print card_id

print (date)
print (time1)
lcd.lcd_backlight("ON")
lcd.lcd_display_string(card_id, 1)
lcd.lcd_display_string(time1, 2)


try:
connection = pymysql.connect(host="localhost", user="USER", passwd="geheim", db="Zeiterfassung")
except:
print "Keine Verbindung zum Server"
exit(0)
#Tabelle erzeugen

cursor = connection.cursor()
cursor.execute("INSERT INTO februar (rfid, date, time, login) VALUES (%s, %s, %s, %s)",(card_id, date, time1, "x"))

cursor.close()
connection.commit()


time.sleep(3)

lcd.lcd_clear()
lcd.lcd_backlight("OFF")

Vielen Dank.
Sollte ich irgendwelche Forenregeln verletzt haben, bitte ich um einen freundlichen Hinweis
freundliche Grüße Andre
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Zuerst einmal zum Datenbankdesign: Informationen sollte man nicht in den Tabellennamen speichern. Es gibt auch keine letzte Zeile, weil Datenbanktabellen keine Ordnung haben. Wenn man den neusten Eintrag haben möchte, dann sucht man nach dem Tabelleneintrag mit dem maximalen Datum.
Datum und Uhrzeit sollten nicht in zwei verschiedenen Spalten stehen. Ebensowenig Login und Logout, weil das nur eine Information mit zwei Zuständen ist.
Die Tabelle sollte daher so aussehen:

Code: Alles auswählen

RFID, Datetime, Login_Logout
und es gibt nur eine Tabelle geben, nicht eine für jeden Monat.

Zum Code: keine nakten excepts. Die Fehlermeldung zur Datenbank hat keine Information, daher das exception-Handling hier komplett weglassen, der Effekt ist der selbe: das Programm beendet sich, nur dass zusätzlich noch Informationen ausgegeben, warum.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Information die du suchst ist einfach in der Anzahl der zu einer ID gespeicherten Eintraege vorhanden. Ist sie gerade (0, 2, ...), dann ist es ein login. Ist sie ungrade, dann ist es ein logout. Womit die Information zu speichern auch redundant ist: du kannst sie deiner momentan Logik entsprechend eh immer inferieren.

Das eigentliche Problem ist aber dein gesamter Ansatz. Da der sich darauf verlaesst, dass es immer paarweise logins und logouts gibt, und dies in der Realitaet nicht so sein wird, ist er fehlerhaft. Sei es, dass ein Kollege vergisst, sich auszuloggen am Abend, und dann am naechsten morgen wieder reinkommt. Sei es, dass die Anlage oder nur ein Tag einen Defekt hat - du stehst am Ende IMMER mit korrupten Daten da. Solange du das Ganze also nicht mit einer Vereinzelungsanlage verbindest, die so teuer ist, dass die vermeintlich gesparten Kosten mit dem PI dagegen Peanuts sind, ist das so kein tragfaehiges System.

Spar dir also das login/logout Gefummel, und speicher einfach die blanken Ereignisse. Basierend darauf kannst du dann zB einen Excel-Report erzeugen, der dann jeden Tag individuell betrachtet. Wenn da alle Ereignisse gut zueinendar passen - fein. Wenn nicht, dann muss man halt diskutieren, was da passiert ist, und die Daten nachtraeglich veraendern.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: naja, man könnte ja schon mit einem Knopf explizit sagen, ob man gerade geht oder kommt. Der Mitarbeiter wird das hoffentlich wissen. Von daher macht eine Spalte dafür durchaus Sinn. Auch sonst, wenn man nachträglich Daten korrigiert, ist so eine Spalte nützlich, wo sonst sollte man diese Information speichern?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: ein Knopf schliesst Fehl- bzw Nichtbedienung genauso wenig aus. Und mein Vorschlag besteht darin, die *Erfassung* der Daten von deren nachtraeglicher Bearbeitung (und dem festhalten dieser Bearbeitung) zu trennen. Denn dann will man ggf. noch ganz andere Informationen festhalten, wo einem eine solche Spalte auch nichts nuetzt. ZB das das System defekt war, die Lagerhalle abgebrannt und darum alle Leute rausgerannt sind, ohne sich um den RFID-Reader zu kuemmern, etc.Das ist IMHO der bessere Ansatz, als die eigentlichen Daten zu massieren.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: das ist eine Designentscheidung, ob man die Daten in einer Tabelle möchte, oder noch eine zusätzliche irgendwo sonst. Bisher sehe ich noch nicht, welche Vorteile eine weitere Tabelle hätte.
Loewe310
User
Beiträge: 4
Registriert: Montag 5. November 2018, 09:18

Hallo,
ja das stimmt auch ein Knopf schließt eine Fehlbedienung nicht aus. (Und in der Excel hockt der Arbeitsplan der (= wenn der chef dir in der Dienstplanung ein M einträgt dann addiere bitte 8 Stunden auf das Arbeitskonto) und dagegen würde ich gern Zuspätkommer und Pausenüberzieher gegenrechnen. Jetzt alles über Zettelwirtschaft. )) Aber wenn da zu viele Fehler vorhanden sind dann lass ich das eh sein.... oder kann ich vieleicht am Ende über php sehen wer gerade in der Pause sitzt.....?

Ich experimentiere hier nur für mich ohne Auftrag. Aus Spaß an der Freude.

Und eigentlich reden wir gerade darüber, ob das alles einen Sinn macht. Ich bin mir nicht sicher ob ich das jemals einsetzen werde. momentan würde ich eigentlich nur dazulernen, wie ich die Datenbank Abfrage
Meinetwegen auch erst einmal alle Datensätze des gelesenen Chips, Vergesst mmal bitte kurz das es um eine Zeiterfassung geht.
Ich bin euch wirklich Dankbar für die Denkanstöße.

Danke
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: klar ist das eine Designentscheidung - ich schlage ja ein anderes Systemdesign vor, bei dem die Rohdaten nur erfasst, aber dann mit einer komplett anderen Pipeline verabeitet werden. ZB mit Excel als maechtigem Tool, mit dem man vieles erreichen kann, ohne zu programmieren. Wenn man in der Tabelle alles abhandeln will, braucht man eben auch viel mehr Code, um die Bearbeitung eben dieser Tabelle darzustellen. Das ist doch auch eine Designentscheidung.

@Loewe310: deine Frage ist doch eigentlich schon beantwortet: Sirius3 hat dich darauf hingewiesen, dass zwei Spalten overkill sind. Und ich hab' dir gesagt, dass ein einfaches zaehlen der Eintraege (SELECT COUNT(*) FROM besserer_tabellenname_als_februar WHERE rfid = ?) die Loesung ist.
Loewe310
User
Beiträge: 4
Registriert: Montag 5. November 2018, 09:18

Vielen Dank,

dann versuche ich das mal umzusetzen.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn man doch ein Anwesend-Flag haben will, die von mir präferierte Lösung, sähe die Abfrage so aus:

Code: Alles auswählen

SELECT zeitstempel, anwesend FROM zeiterfassung WHERE rfid = ? ORDER BY zeitstempel LIMIT 1
Mit der aktuellen Zeit und dem Zeitstempel läßt sich dann auch einfach eine Heuristik schreiben, ob da ein Buchungsvorgang vergessen wurde.
Loewe310
User
Beiträge: 4
Registriert: Montag 5. November 2018, 09:18

auch dafür dann lieben Dank. Ich schau mal ob ich zurecht komme.
Antworten