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 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代码来逐日计算每个用户登录和注销之间的分钟差异。 但是可能存在一些问题,例如:
有智能解决方案(可能只有MySQL)或者我必须使用PHP并制作代码墙吗?
答案 0 :(得分:0)
可能的解决方案如下:
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 :(得分:0)
我认为这个解决方案有所帮助。作为基础每次登录由logout流动来解释这里的代码 我加入所有登录记录(排名)和所有登出记录(排名) 因此,如果一次登录将计数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
我从内到左进行了更改连接,所以我一次登录并且没有注销,并且从行号到按日排名所以每天都会计入登录/注销从1开始,我曾经用Microsoft SQL Server执行此操作。 让我们开始解释查询如何工作我需要的第一个数据 但首先你需要准备好以下思考的步骤: 答:我需要数据(&#39;退出记录&#39;以及&#39;登录记录&#39;)&lt; - 这里您可以应用每日选择或最大值或相同值的逻辑 B.然后我想应用条件来获取这些数据并正确过滤它 - 这里完成加入登录和注销记录,以便你可以正确匹配它们
1.我希望获得每个用户的所有登录操作,并使用变量@row_counter
为每一行提供一个数字,并为每一行增加1
select id,
timedate as timedate, # here you can use max() to get max login in day
user,
action, # action will be login since it specified at where clause
@row_counter1 := if(@perv_day1 <> 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_counter1 :=0) x # here I define the row with 0
(select @perv_day1 :=0) y # to track rank for each row
where userLogs.action ='login'
group by user # here i group each user
, DAY( userLogs.timedate ) # also you can group by day
出:
id timedate user action rowRankedByDay
1 2010-01-01 10:01:01 AB991 login 1
3 2010-01-01 14:01:01 AB991 login 2
5 2010-01-01 10:01:01 ZM991 login 3
7 2010-01-02 10:01:01 AB991 login 1
9 2010-01-02 10:01:01 ZM991 login 2
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
out
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
很抱歉,如果这里有更多代码,;)我希望这对你有帮助。