nativemode
Goto Top

MySQL Zeiterfassungs-Problematik (wer ist eingecheckt)

Hallo,
nach längerer Zeit melde ich mich noch mal mit einem (My)SQL-Problem. Ich schreibe an einem Zeiterfassungs-Tool welches User beim Ein- und Auschecken mit Zeitstempel erfasst.
Diese Tabelle sieht so aus, hier mit Beispiel-Daten gefüttert:
mysql> select * from log;
+-------+--------+---------+---------------------+---------------------+
| index | member | station | in                  | out                 |
+-------+--------+---------+---------------------+---------------------+
|     1 |  11753 |       1 | 2017-05-26 09:37:50 | 2017-05-26 09:46:24 |
|     2 |  11753 |       1 | 2017-05-26 09:51:27 | 2017-05-26 15:00:42 |
|     3 |  11753 |       1 | 2017-05-27 07:29:28 | NULL                |
|     4 |  18559 |       1 | 2017-05-27 09:53:32 | 2017-05-27 15:14:59 |
|     5 |    362 |       1 | 2017-05-27 14:58:05 | NULL                |
|     6 |    423 |       1 | 2017-05-27 14:59:33 | 2017-05-27 15:31:15 |
|     7 |  11753 |       1 | 2017-05-27 15:01:24 | 2017-05-27 15:08:56 |
+-------+--------+---------+---------------------+---------------------+
Beim Ein/Auscheck-Vorgang schaut eine MySQL-Funktion zunächst nach einen "offenen" Zeitpaar. Wenn eines gefunden wird, wird die Ausgangs-Zeit eingetragen und der User ist Ausgecheckt. Wir kein offenes Zeitpaar gefunden wird ein neues Datensatz mit Eingangs-Zeit erstellt und der User ist eingecheckt.

Jetzt kam der Wunsch man möchte doch bitte sehen können wer jetzt im Augenblick alles eingecheckt ist. Dazu habe ich folgende Abfrage gebastelt:
SELECT `member`, `in`, `members`.`firstname`, `members`.`lastname` FROM `log` 
LEFT JOIN `members` ON `log`.`member` = `members`.`id` 
WHERE DATE(`in`) = CURDATE() AND `out` IS NULL
ORDER BY `in` DESC
Die Abfrage holt sich noch den Klarnamen aus der "Members"-Tabelle. Wenn ich sie ausführe, kommt (nicht ganz falsch) folgendes raus:
+--------+---------------------+-----------+----------+
| member | in                  | firstname | lastname |
+--------+---------------------+-----------+----------+
|    362 | 2017-05-27 14:58:05 | Donald    | Duck     |
|  11753 | 2017-05-27 07:29:28 | Peter     | Parker   |
+--------+---------------------+-----------+----------+

Das Problem ist jetzt aber folgendes: User 11753 (Parker) ist eigentlich gar nicht mehr eingecheckt sondern hat sich zu einem anderen Zeitpunkt nicht abgemeldet. Das kommt leider häufig vor. Die Ein/Auscheck-Funktion hat deshalb eine Maximal-Zeit, nach der ein erneuter Checkin stattfindet und das vorherige Zeitpaar offen bleibt.

Gibt es irgendeinen Weg dies in der Abfrage zu berücksichtigen? Also z.B. nicht mehr weiter zu suchen wenn ein "geschlossenes" Zeitpaar neuer ist als das offene?

Content-Key: 339105

Url: https://administrator.de/contentid/339105

Ausgedruckt am: 19.03.2024 um 07:03 Uhr

Mitglied: Sheogorath
Sheogorath 27.05.2017 aktualisiert um 16:25:00 Uhr
Goto Top
Moin,

Gibt es irgendeinen Weg dies in der Abfrage zu berücksichtigen? Also z.B. nicht mehr weiter zu suchen wenn ein "geschlossenes" Zeitpaar neuer ist als das offene?

Mhm, ist vielleicht nicht genau das was du willst, aber theoretisch kann allein schon Arbeitsrechtlich niemand länger als 24h eingecheckt sein, wie wäre es also du fragst einfach nur die letzten 24h ab?

Edit:

Ansonsten geht natürlich auch:

SELECT member, MAX(in), firstname, lastname FROM `test` GROUP BY member

Gruß
Chris
Mitglied: wiesi200
wiesi200 27.05.2017 um 16:23:23 Uhr
Goto Top
Hallo,

Im Endeffekt brauchst du doch eh noch eine Alarmliste für Leute die das abmelden vergessen haben. Damit man die Zeiten korrigieren kann um korrekte Arbeitszeiten zu haben.

Grundsätzlich würde ich mir einen Select auf die Benutzer machen, dann mit einem subselect den letzten Buchungssatz des Benutzers raus suchen. Wenn der OUT wert leer ist dann sollte er noch da sein.
Mitglied: Biber
Lösung Biber 27.05.2017 aktualisiert um 17:18:45 Uhr
Goto Top
Moin NativeMode,

Du kannst deine obige Abfrage erweitern um eine weitere WHERE-Bedingung.

... and Not exists (
select 1 from Log l2 where
L2.member=log.member And l2.in > Log.in)
...

Grüße
Biber
Mitglied: Codehunter
Codehunter 28.05.2017 um 09:19:45 Uhr
Goto Top
Wäre es nicht das einfachste mit einem GROUP BY member und einem ORDER BY in?
Mitglied: Arano
Arano 28.05.2017 um 11:22:16 Uhr
Goto Top
Moin

Die Ein/Auscheck-Funktion hat deshalb eine Maximal-Zeit, nach der ein erneuter Checkin stattfindet und das vorherige Zeitpaar offen bleibt.
Anstelle es offen zu lassen, setze es doch auf 1970-01-01 01:00:00 oder 2999-12-31 also auf einen unmöglichen Wert. Danach kannst du dann auch in weiteren Queries filtern.
Den Check lässt du dann auch beim Anzeigen der Übersicht ausführen bevor du die aktualisierten Daten ausliest und anzeigst.

So kannst du dann auch mal schauen wie oft sich nicht ausgeloggt wird (1970) oder wie oft ein User sich "ein zweites mal" einloggen wollte (2999).

~ Arano
Mitglied: Pedant
Pedant 28.05.2017 um 12:00:23 Uhr
Goto Top
Hallo NativeMode;

Zitat von @NativeMode:
nach längerer Zeit melde ich mich noch mal mit einem (My)SQL-Problem. Ich schreibe an einem Zeiterfassungs-Tool welches User beim Ein- und Auschecken mit Zeitstempel erfasst.

Nur nebenbei erwähnt:
Ich hatte in einem anderen Thread auf die Anfrage "Suche einfache (webbasierte) Stempeluhr mit Exportfunktion" als Antwort ein komplettes Zeiterfassungssysten auf Basis php/MySQL geschrieben und dort verlinkt.
Suche einfache (webbasierte) Stempeluhr mit Exportfunktion
Vielleicht ist das für Dich auch interessant (als Anregung oder gar als Lösung).

Gruß Frank
Mitglied: NativeMode
NativeMode 28.05.2017 um 13:19:26 Uhr
Goto Top
Hallo,
Zunächst mal Danke für die vielen Lösungsansätze und Anregungen. Der Vorschlag von Biber war letztendlich das was ich gesucht habe.

@Biber
vielen Dank dafür. Leider verstehe ich den Befehl mit l2 nicht komplett, könntest du das eventuell erklären? Funktionieren tut es jedenfalls.

@alle
Ich habe mein System tatsächlich schon in einem Fitness-Studio im Einsatz, baue jetzt nach und nach weitere Wunsch-Funktionen ein.
Es besteht bisher aus einem Linux-PC auf dem der MySQL-Server läuft sowie das Verwaltungsprogramm und ein Selbst-Checkin mit Barcode-Leser. Zusätzlich ist an der Eingangstür ein Terminal (besteht aus Arduino-Yun, Display, Relais und Barcode-Scanner) zur Zugangskontrolle eingebaut.

Wünsche euch noch einen schönen Sonntag!
Mitglied: Biber
Biber 28.05.2017 aktualisiert um 17:18:43 Uhr
Goto Top
Moin NativeMode,

Da die Tabelle Log ja schon im Select eingebunden ist und ich ein zweites Mal darauf zugreifen wollte - mit anderen Kriterien, nämlich einem Vergleich mit den aktuellen Werten aus Tabelle Log - musste ich eben einen anderen Alias verwenden. Mangels Kreativität habe ich L2 genommen.

Grüße
Biber
Mitglied: wiesi200
wiesi200 28.05.2017 um 16:01:15 Uhr
Goto Top
Hallo,

Ich würde da am Tagesende alle Buchungen mit nem Wartungslauf enden lassen. Wobei hier auf meiner Einschätzung nach ein Filter auf den Aktuellen Tag reicht. Die Leute werden ja sicher nicht über Mitternacht hinaus Trainieren, oder?