Php 带子句的时间戳
我对MySQL查询有一个小问题: 桌子是这样的Php 带子句的时间戳,php,mysql,Php,Mysql,我对MySQL查询有一个小问题: 桌子是这样的 id timedate user action 1 2010-01-01 10:01:01 AB991 login 2 2010-01-01 12:01:01 AB991 logout 3 2010-01-01 14:01:01 AB991 login 4 2010-01-01 18:01:01 AB991 logout 5 2010-01-01 10:01:01 ZM991 login 6 201
id timedate user action
1 2010-01-01 10:01:01 AB991 login
2 2010-01-01 12:01:01 AB991 logout
3 2010-01-01 14:01:01 AB991 login
4 2010-01-01 18:01:01 AB991 logout
5 2010-01-01 10:01:01 ZM991 login
6 2010-01-01 10:01:01 ZM991 logout
7 2010-01-02 10:01:01 AB991 login
8 2010-01-02 18:01:01 AB991 logout
9 2010-01-02 10:01:01 ZM991 login
现在,我需要一个查询,或者一些PHP代码,每天为每个用户计算登录和注销之间的分钟差。
但也有一些问题,比如:
可能没有注销日志
有可能一天我有2次登录和2次注销操作或更多。
有一个聪明的解决方案,可能只有MySQL,或者我必须使用PHP并制作一堵代码墙?一个可能的解决方案如下:
select id, timedate, action
from mytable
where user = 'AB991'
order by timedate
您的PHP代码将按日期获得一个有序列表。算法应该如下所示:
$user = 'AB991';
$stmt = $db->prepare("select id, timedate, action from mytable where user = ? order by timedate");
$stmt->execute(array($user));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
$previousTime = "";
foreach ($rows as $row) {
if ($row["action"] === "login") {
$previousTime = strtotime($row["timedate"]);
} else if ($row["action"] === "logout") {
if ($previousTime === "") {
//duplicate logout
} else {
//add the remaining time to the day when the user logged in
//add the whole days passed between log in and log out
//add the start of the last day when the user logged in
$previousTime = "";
}
}
}
问题:
用户可以分别使用不同的会话登录
用户可能无法注销
用户可能会使用其他会话注销
建议:我将修改该表以包含会话id和最后一个操作。当用户执行一个操作时,最后一个操作的时间戳将被更新,因此您将有一个基于会话的数据,其中每一行都会代表自己,显示登录时间和最后一个操作时间。我认为这个解决方案会有所帮助。作为基础,每个登录都会通过注销来解释这里的代码 我加入所有登录记录排名和所有注销记录排名 因此,如果一个登录计数为1,并且如果由注销计数1流动,则将被选中
select
logIn. *, logOut.* ,
TIMESTAMPDIFF(MINUTE, logIn.timedate, logOut.timeDate) as howLongUserStaysInMinutes
from (SELECT @row_counter1 := 0) x,
(SELECT @row_counter2 := 0) y,
(select userLogs.* , @row_counter1 := @row_counter1 +1 as row
from userLogs
where userLogs.action ='login') as logIn
left join (select * , @row_counter2 := @row_counter2 + 1 as row
from userLogs
where userLogs.action = 'logout') as logOut
on logOut.user = logIn.user
and ( logIn.timedate <= logOut.timedate || logOut.timedate is null)
and logIn.row = logOut.row
输出:
2.我对注销操作也做了同样的操作
select id,
timedate as timedate, # here you can use max() to get max login in day
user,
action, # action will be logout since it specified at where clause
@row_counter2 := if(@perv_day2 <> DAY( userLogs.timedate ) , 1 , @row_counter1 +1) rankedByDay,
@perv_day1 := if(@perv_day1 <> DAY( userLogs.timedate ) , DAY( userLogs.timedate ) , @perv_day1) _day
from userLogs ,
(select @row_counter2 :=0) y # here I define the row with 0
(select @perv_day2 :=0) y # to track rank for each row
where userLogs.action ='logout'
group by user # here i group each user
现在我有了数据,我想加入他们,这样我可以找到时间的差异,但是需要什么样的条件才能这样做
select TIMESTAMPDIFF(MINUTE, logIn.timedate, logOut.timeDate) as howLongUserStaysInMinutes
from logIn
left join logOut on (logOut.user = logIn.user) # same user
and DAY( logIn.timedate ) = DAY( logOut.timedate ) # action at the same day
and logIn.rowRankedByDay= logOut.rowRankedByDay # login and logout actions rows
and ( logIn.timedate <= logOut.timedate || logOut.timedate is null) # login was before logout or user did not logout
抱歉,如果这里有更多代码;我希望这对你有帮助 您已经尝试过的查询是什么?这是我自己已经尝试过的,但是有很多问题。明天我会试试你的代码,也许比我的更干净。谢谢。嗯,我很难理解你所有的代码,但明天我会尝试,如果它能工作,我会让你知道。谢谢好的,在这个查询中有一个小问题我不知道如何处理,结果是第一次登录(例如2016-01-15 11:39:35)和第一次注销(例如2016-01-22 11:25:33)之间存在差异。只有当它们在同一天时,我才需要计算差异。我甚至每天都可以做这个查询。有什么帮助吗?另一个问题,如果我在同一天有2个登录和1个注销,查询必须取最大值,并放弃另一个。例如:2016-01-25 11:02:54->登录| 2016-01-25 14:08:49->登录| 2016-01-25 14:09:19->注销我需要第二次登录和注销之间的差异谢谢。谢谢,但现在的问题是:我如何将所有代码放在一个查询中?我无法创建视图,因为它包含变量。我分别进行了3次查询,结果是N行为NULL。问题:有一种方法我可以给你发送真实数据库的表吗?谢谢确定找到了错误,在注销查询rankedbyday总是空的,现在我搜索原因。
select id,
timedate as timedate, # here you can use max() to get max login in day
user,
action, # action will be logout since it specified at where clause
@row_counter2 := if(@perv_day2 <> DAY( userLogs.timedate ) , 1 , @row_counter1 +1) rankedByDay,
@perv_day1 := if(@perv_day1 <> DAY( userLogs.timedate ) , DAY( userLogs.timedate ) , @perv_day1) _day
from userLogs ,
(select @row_counter2 :=0) y # here I define the row with 0
(select @perv_day2 :=0) y # to track rank for each row
where userLogs.action ='logout'
group by user # here i group each user
id timedate user action rowRankedByDay
2 2010-01-01 12:01:01 AB991 logout 1
4 2010-01-01 18:01:01 AB991 logout 2
6 2010-01-01 10:01:01 ZM991 logout 3
8 2010-01-02 18:01:01 AB991 logout 1
select TIMESTAMPDIFF(MINUTE, logIn.timedate, logOut.timeDate) as howLongUserStaysInMinutes
from logIn
left join logOut on (logOut.user = logIn.user) # same user
and DAY( logIn.timedate ) = DAY( logOut.timedate ) # action at the same day
and logIn.rowRankedByDay= logOut.rowRankedByDay # login and logout actions rows
and ( logIn.timedate <= logOut.timedate || logOut.timedate is null) # login was before logout or user did not logout