2011-01-20 11 views
12

Mam tabelę MySQL, w której rejestrowane są czasy logowania pracowników i wylogowania. Tutaj w kolumnie wejściowej 1 - oznacza login, a 0 - oznacza wylogowanie.Uzyskaj całkowitą liczbę przepracowanych godzin w ciągu dnia mysql

[id] [User_id]   [Date_time]     [in_out] 
    1  1   2011-01-20 09:30:03     1 
    2  1   2011-01-20 11:30:43     0 
    3  1   2011-01-20 11:45:12     1 
    4  1   2011-01-20 12:59:56     0 
    5  1   2011-01-20 13:33:11     1 
    6  1   2011-01-20 15:38:16     0 
    7  1   2011-01-20 15:46:23     1 
    8  1   2011-01-20 17:42:45     0 

Czy możliwe jest pobranie całkowitej liczby przepracowanych godzin dziennie przez użytkownika za pomocą pojedynczego zapytania?

Próbowałem dużo, ale wszystko na próżno. Mogę to zrobić w PHP przy użyciu tablicy, ale nie można tego zrobić przy użyciu pojedynczego zapytania.

+1

Z technicznego punktu widzenia nie jest to możliwe, ale jeśli szukasz czasu pomiędzy momentem, w którym się on dostał, a chwilą na zewnątrz, to możliwe! –

+0

@Alan: tak, jest. – ash

+1

@Jasie: Żartowałem, że czas spędzony na pracy nie jest równy różnicy między czasem zegarowym a czasem wyczekiwania. –

Odpowiedz

4
SELECT `User_id`, time(sum(`Date_time`*(1-2*`in_out`))) 
    FROM `whatever_table` GROUP BY `User_id`; 

The (1-2 * `in_out`) określenie daje każde zdarzenie logowaniu -1 czynnik i każde zdarzenie wylogowania Czynnikiem +1. Funkcja sum przyjmuje sumę kolumny Date_time, a GROUP BY "User_id" powoduje utworzenie sumy dla każdego innego użytkownika.

+0

Gdy 'in_out' wynosi 1, to jest to (1-2 * 1) = - 1, które powoduje, że pole' Date_time' dla tego rzędu ujemny. Gdy 'in_out' ma wartość 0, to jest to (1-2 * 0) = 1, a wiersz' Date_time' nie zostanie zmieniony. Tak więc funkcja 'sum' widzi dodatnią wartość dla każdego wylogowania i ujemną wartość dla każdego zalogowania. Zatem wynikiem 'sum' jest każde zdarzenie wylogowania, odejmowane przez każde zdarzenie logowania. Funkcja czasu wokół sumy służy do wyraźniejszego wyjścia, ponieważ wynik sumy jest wartością daty i czasu, gdzieś w okolicach roku 1 stycznia 0. – Rudi

+0

jest to naprawdę twórcze rozwiązanie. Kocham to. –

+0

To nie działa http://sqlfiddle.com/#!9/45870/1/0 –

0

spróbuj tego:

select [User_id], sum([Time_count])/3600 
from (
    select [User_id], 
     case when [in_out]=1 then UNIX_TIMESTAMP([Date_time]) 
       when [in_out]=0 then - UNIX_TIMESTAMP([Date_time]) 
       end as [Time_count] 
    from my_table 
) as a 
group by [User_id] 

nie wiem składni MySQL, więc jeśli ktoś znajdzie błędy, należy je poprawić. Może nie działa. Na przykład, jeśli masz zalogowanego użytkownika. W takim przypadku możesz filtrować tylko tych użytkowników, którzy mają ten sam numer 1 i 0 w polu [in_out].

4

Linia myślenia Rudiego jest poprawna. Jeśli chcesz godzin z dziesiętnym, użyj UNIX_TIMESTAMP() w polu date_time, w przeciwnym razie zwracany typ będzie DATETIME (trudne do parsowania). Oto wynik dla pierwszych 4 linii danych plus 2 więcej dla innego dnia:

SELECT 
    `user_id`, 
    DATE(`date_time`) AS `date`, 
    SUM(UNIX_TIMESTAMP(`date_time`)*(1-2*`in_out`))/3600 AS `hours_worked` 
FROM `test` 
GROUP BY date(`date_time`), `user_id`; 
+---------+------------+--------------+ 
| user_id | date  | hours_worked | 
+---------+------------+--------------+ 
|  1 | 2011-01-20 |  3.2567 | 
|  1 | 2011-01-21 |  3.0000 | 
+---------+------------+--------------+ 
+0

Możesz zamienić "date (' date_time') "w GROUP BY na" date ", ponieważ zostało zdefiniowane w wyrażenie SELECT już. – Clutch

Powiązane problemy