2015-05-07 2 views
1

У меня есть следующая структураполучить разницу во времени от Чайлдс

---------- 
presences 
---------- 
id 
started 
ended 
user_id 

--------- 
breaks 
--------- 
id 
presence_id 
started 
ended 

Мне нужно создать запрос SQL, который возвращает мне следующую информацию

presence_id user_id presence_time breaks_time

где время присутствия (presence.ended - наличие - начато) - сумма (break.ended - break.started) всех разрывов, связанных с наличием

Есть ли эффективный способ ge t эта информация с sql-запросом?

Если вы знаете, как сделать это в красноречивой, было бы еще лучше: D

Спасибо так много!

+0

Ваш начальный и закончился отметки времени или даты? –

+0

это отметка времени –

ответ

2

http://sqlfiddle.com/#!9/650a2/3

SELECT p.id presence_id, 
    p.user_id, 
    (p.ended-p.started) presence_time , 
    SUM(b.ended-b.started) breaks_time 
FROM presences p 
LEFT JOIN breaks b 
ON p.id = b.presence_id 
GROUP BY p.id 

UPDATE же запрос, сгруппированные по user_id:

http://sqlfiddle.com/#!9/1ce21/1

SELECT 
    sub_total.user_id, 
    SUM(sub_total.presence_time) , 
    SUM(sub_total.breaks_time) 
FROM (
SELECT p.id presence_id, 
    p.user_id, 
    (p.ended-p.started) presence_time , 
    SUM(b.ended-b.started) breaks_time 
FROM presences p 
LEFT JOIN breaks b 
ON p.id = b.presence_id 
GROUP BY p.id) sub_total 
GROUP BY sub_total.user_id 
+0

, которая работает только в том случае, если его начальное и конечное число числовое? –

+0

почему? он работает, если mysql может выполнять минус '-' между этими двумя полями. Поскольку он не установлен в OP, я устанавливаю его в int, но вы можете попробовать все, что захотите. Запрос не изменится много, это просто литье. – Alex

+0

Огромное спасибо! он работал, проверьте мой собственный ответ, чтобы увидеть мой последний запрос с отметками времени. –

0

Благодаря @Alex я получил это работает, мой последний запрос следующим образом (с использованием временные метки)

SELECT *, 
     TIME_TO_SEC(TIMEDIFF(p.ended,p.started)) as presence_time, 
    sum(TIME_TO_SEC(TIMEDIFF(b.ended,b.started))) as breaks_time 

FROM presences p 
left join presences_breaks b on b.presence_id = p.id 
group by p.id 
+0

Поскольку вы не предоставляли скрипку, я не уверен, что ваш запрос будет работать :-) 'sum (TIME_TO_SEC (TIMEDIFF (p.ended, p.started))) как presence_time, 'is wrong. если вы проверите его с любым набором данных, в котором у вас есть 2 перерыва или более - вы увидите, что время ожидания будет умножаться столько раз, сколько у вас будет. поэтому он должен быть 'TIME_TO_SEC (TIMEDIFF (p.ended, p.started)) как presence_time,' – Alex

+0

Вы правы! сумма для presence_time была многократной! –

+0

, а теперь, если я хочу сгруппировать по user_id? –

1

Если started и ended сохраняются как datetime или timestamp, то вы можете легко сделать расчет и найти данные в течение нескольких минут. Следующий пример будет полезен, если кто-то совершит несколько коротких перерывов в рабочее время.

Позже на уровне приложения вы можете конвертировать минуты в час. Вот как вы можете это сделать в mysql

mysql> select * from presence ; 
+------+---------------------+---------------------+---------+ 
| id | started    | ended    | user_id | 
+------+---------------------+---------------------+---------+ 
| 1 | 2015-01-01 09:00:00 | 2015-01-01 18:00:00 |  10 | 
| 2 | 2015-01-01 09:20:00 | 2015-01-01 18:04:00 |  11 | 
| 3 | 2015-01-01 09:10:00 | 2015-01-01 18:30:00 |  12 | 
| 4 | 2015-01-02 09:23:10 | 2015-01-02 18:10:00 |  10 | 
| 5 | 2015-01-02 09:50:00 | 2015-01-02 19:00:00 |  11 | 
| 6 | 2015-01-02 09:10:00 | 2015-01-02 18:36:30 |  12 | 
+------+---------------------+---------------------+---------+ 
6 rows in set (0.00 sec) 

mysql> select * from breaks ; 
+------+-------------+---------------------+---------------------+ 
| id | presence_id | started    | ended    | 
+------+-------------+---------------------+---------------------+ 
| 1 |   1 | 2015-01-01 12:00:00 | 2015-01-01 12:20:30 | 
| 2 |   1 | 2015-01-01 15:46:30 | 2015-01-01 15:54:26 | 
| 3 |   2 | 2015-01-01 11:26:30 | 2015-01-01 11:34:23 | 
| 4 |   2 | 2015-01-01 14:06:45 | 2015-01-01 14:10:20 | 
| 5 |   2 | 2015-01-01 16:01:10 | 2015-01-01 16:14:57 | 
| 6 |   3 | 2015-01-01 12:11:20 | 2015-01-01 12:40:05 | 
| 7 |   3 | 2015-01-01 17:01:10 | 2015-01-01 17:24:21 | 
| 8 |   4 | 2015-01-02 12:50:00 | 2015-01-02 13:40:00 | 
| 9 |   5 | 2015-01-02 12:20:00 | 2015-01-02 13:05:30 | 
| 10 |   5 | 2015-01-02 17:03:00 | 2015-01-02 17:20:00 | 
| 11 |   6 | 2015-01-02 12:16:50 | 2015-01-02 12:58:30 | 
+------+-------------+---------------------+---------------------+ 
11 rows in set (0.00 sec) 



select 
p.id as presence_id, 
p.user_id, 
timestampdiff(minute,started,ended) - b.break_time as presence_time, 
b.break_time from presence p 
left join (
select 
presence_id, 
coalesce(sum(timestampdiff(minute,started,ended)),0) as break_time 
from breaks 
group by presence_id 
)b 
on b.presence_id = p.id 

+-------------+---------+---------------+------------+ 
| presence_id | user_id | presence_time | break_time | 
+-------------+---------+---------------+------------+ 
|   1 |  10 |   513 |   27 | 
|   2 |  11 |   501 |   23 | 
|   3 |  12 |   509 |   51 | 
|   4 |  10 |   476 |   50 | 
|   5 |  11 |   488 |   62 | 
|   6 |  12 |   525 |   41 | 
+-------------+---------+---------------+------------+ 
6 rows in set (0.00 sec) 
+0

Большое вам спасибо! он работает так, как ожидалось: D –

Смежные вопросы