Proszę o pomoc z zapytaniem SQL

0

Mam tabelę z wejściami i wyjściami pracowników.
Wygląda to tak:
2019-04-01 0501 WEJ
2019-04-01 1105 WYJ
2019-04-01 1312 WEJ
2019-04-01 1444 WYJ

Czy da się jakoś zapytaniem wyliczyć czas pracy?

1

Da się, jak użyjesz np. TIMESTAMPDIFF na odpowiednich rekordach :) Tylko spasowanie odpowiednich rekordów może być kłopotliwe. Ale masz różne opcje:

  • odfiltrować sobie wszystkie daty wejścia i w odnaleźć pasujące daty wyjścia, czyli dla każdego wejścia X taką datę wyjścia Y, która będzie najwcześniejsza ze wszystkich dat wyjścia, ale tylko tych późniejszych niż X. Jak dla mnie rozwiązanie słabe, bo musiałbyś np. napisać subquery odpalane dla każdego z wejść, które by sobie wyciągało odpowiednie wyjście. Będzie pewnie dość wolne dla dużej liczby rekordów.
  • próbować hackować tzn. jeśli interesuje Cię tylko całkowity czas pracy, najpierw zsumować np. różnice czasu między każdym rekordem a jakąs referencyjną datą (np CURRENT_TIMESTAMP()), zsumować osobno różnice dla wejść i wyjść i odjąć - pomijając corner case'y np. ktoś wszedł a nie wyszedł, powinieneś dostać sumaryczny czas pracy pracownika
  • przerobić tabelę tak, by w jednym rekordzie trzymany był zarówno czas wejścia, jak i wyjścia. Wtedy możesz bardzo łatwo to zrobić bez żadnych subquery i czarowania, po prostu na każdym rekordzie robiąc sobie jakiś TIMESTAMPDIFF między dwiema kolumnami. Dodatkowo unikniesz błędów (chyba że masz jakieś triggery/checki które robią walidację) typu "ktoś zapomniał zalogować jedno wyjście, więc pracownik wyszedł dwa razy z rzędu" - po prostu odfiltrujesz błędne rekordy i będziesz mógł je łatwo wykryć. Wyglądałoby to wtedy dość banalnie:
# Czasy pracy per wejście/wyjście
SELECT WORKER_ID, TIMESTAMPDIFF(HOUR, ARRIVAL_DT, DEPARTURE_DT) AS UPTIME FROM MY_TABLE;
# Sumaryczny czas pracy
SELECT WORKER_ID, SUM(TIMESTAMPDIFF(HOUR, ARRIVAL_DT, DEPARTURE_DT)) AS TOTAL_UPTIME FROM MY_TABLE GROUP BY WORKER_ID;
0

Tak na szybko: http://sqlfiddle.com/#!18/a615a/7/0

Oczywiście wszystko zależy od jakości danych. W tym zapytaniu mamy założenie, że zdarzenia WEJ/WYJ następują jedno po drugim.

1

Zakladajac ze nie bedzie brakujacych danych tzn dla kazdego wejscia bedzie wyjscie.

http://sqlfiddle.com/#!18/5878a/2

DECLARE @user_clocking_records TABLE
    (
        empid INT ,
        dt DATETIME ,
        event CHAR(3)
    );

INSERT INTO @user_clocking_records
VALUES ( 1, '2019-04-01 05:59:01', 'WEJ' ) ,
       ( 1, '2019-04-01 11:06:05', 'WYJ' ) ,
       ( 1, '2019-04-01 13:11:12', 'WEJ' ) ,
       ( 1, '2019-04-01 14:56:44', 'WYJ' ) ,
       ( 2, '2019-04-01 05:59:01', 'WEJ' ) ,
       ( 2, '2019-04-01 14:58:44', 'WYJ' ) ,
       ( 1, '2019-04-02 05:59:01', 'WEJ' ) ,
       ( 1, '2019-04-02 12:58:44', 'WYJ' );

SELECT   day ,
         a.empid ,
         SUM(DATEDIFF(MINUTE, a.wej, a.wyj)) min
FROM     (   SELECT empid ,
                    CONVERT(DATE, dt, 111) day ,
                    event ,
                    dt wej ,
                    LEAD(dt) OVER ( ORDER BY empid ,
                                             dt ) wyj
             FROM   @user_clocking_records ) a
WHERE    a.event = 'WEJ'
GROUP BY day ,
         a.empid
ORDER BY a.day ,
         a.empid;

screenshot-20190401123252.png

0

ipsd: Dzięki, rewelacja.

1 użytkowników online, w tym zalogowanych: 0, gości: 1