我正在使用此查询来计算用户在应用中的全天和前5天的登录时间
Select
sec_to_time(sum(time_to_sec(TIMEDIFF((IFNULL(logoff_time, ADDTIME(now(), '05:00:00'))),login_time)))) as online_time
from tb_sessions
WHERE
(login_time BETWEEN DATE(DATE_ADD(now(), INTERVAL (-6) DAY))
AND
ADDTIME(now(), '5:00:00')) AND user_id = 30982
AND TIME(`login_time`) between "00:00:00" AND "23:59:59"
group by DATE(login_time)
现在我有了一些新的要求:
计算从07:00:00到23:59:59的时间
我的表: tb_sessions
id | user_id | login_time | logoff_time
1 3098 2017-06-10 06:30:00 2017-06-10 07:45:00
2 3098 2017-06-10 07:45:01 2017-06-10 08:30:00
通过使用上述查询,总的橄榄色时间是= 02:00:00 但我只想要时间从7:00到8:30,所以总时间将是= 1:30:00 我对查询进行了一些更改,但没有成功。
您可以在以下链接中查看我的查询:
答案 0 :(得分:1)
您可以使用greatest
在同一天使用最新日期login_time
和7:00,然后再次使用greatest
排除负时差(同时注销时)时间是在7:00之前):
Select date(login_time) date,
time_format(sec_to_time(sum(greatest(0, time_to_sec(timediff(
ifnull(logoff_time, now()),
greatest(login_time, date_add(date(login_time), interval 7 hour))
))))), '%H:%i:%s') online
from tb_sessions
where login_time between date(date_add(now(), interval (-3) day)) and now()
and user_id = 3098
and time(login_time) between "00:00:00" and "23:59:59"
group by date(login_time)
上查看它
内部greatest
调用如下所示:
greatest(login_time, date_add(date(login_time), interval 7 hour))
第二个参数仅取自login_time
的日期,因此它对应于当天的午夜,然后为其添加7个小时:因此这表示当天的7:00。 greatest
将返回这两个时间戳中的最新一个。如果第一个参数表示时间而不是7:00,则将返回该参数。如果没有,将返回第二个参数(即7:00)。
外部greatest
调用如下所示:
greatest(0, time_to_sec(timediff(....)))
这将确保时差不是负数。拿这个例子记录:
login_time | logoff_time
----------------+----------------
2017-06-01 6:30 | 2017-06-01 6:45
在这种情况下,最里面的greatest
会返回2017-06-01 7:00
,因为6:30
太早了。但这会使timediff()
返回否定时间间隔:-15分钟。我们真正想要的是0,因为用户在 7:00之后没有时间登录。这是greatest
将执行的操作:greatest(0, -15) = 0
,因此负值将被消除,并且不会影响总和。
login_time
我将条件time(login_time) between "00:00:00" and "23:59:59"
留在那里,但它确实没有做任何事情,因为这一切都是正确的(除非它们是null
,但它们也不会通过第一个条件)
在评论中,您询问如何在用户未在同一天注销但在1或2天后保持在线状态的每一天进行分组。
在这种情况下,您需要一个帮助程序表,列出您希望在输出中查看的所有日期。例如,这可能是最后7天的七个记录。
然后你必须加入你的表,以便至少有一个用户会话与这样一个参考日期的重叠。在线时间的计算必须考虑到注销时间可能不在午夜之前。
以下是更新的查询:
select ref_date date,
time_format(sec_to_time(sum(greatest(0, time_to_sec(timediff(
least(ifnull(logoff_time, now()), date_add(ref_date, interval 1 day ), now()),
greatest(login_time, date_add(ref_date, interval 7 hour))
))))), '%H:%i:%s') online
from ( select date(date_add(now(), interval (-6) DAY)) as ref_date union all
select date(date_add(now(), interval (-5) DAY)) union all
select date(date_add(now(), interval (-4) DAY)) union all
select date(date_add(now(), interval (-3) DAY)) union all
select date(date_add(now(), interval (-2) DAY)) union all
select date(date_add(now(), interval (-1) DAY)) union all
select date(now())
) ref
inner join tb_sessions
on login_time < date_add(ref_date, interval 1 day)
and logoff_time > date_add(ref_date, interval 7 hour)
where user_id = 3098
group by ref_date
在sqlfiddle上看到它。