我有以下结构
----------
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)的总和
是否有一种通过SQL查询获取此信息的有效方法?
如果你知道如何以雄辩的方式做到这一点,那就更好了:D
非常感谢你!
答案 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
更新按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
答案 1 :(得分: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)
答案 2 :(得分: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