MySQL在线计算时间

时间:2010-10-10 01:22:11

标签: mysql coldfusion time

是否可以通过类似

的表格在线计算时间
logtype   time  
----------------
login     2:30  
logout    2:45  
login     3:20  
logout    4:50  
login     5:00  
login     5:10  
logout    6:00  

它会有额外的登录,因为有时服务器崩溃并且不会添加注销。 你能在MySQL中做这样的事情还是你必须使用ColdFusion? 如果是这样,你会如何在MySQL / ColdFusion中做到这一点?

我想要的只是一个(粗略的)特定用户在线,小时,天,分钟等的总时间。

3 个答案:

答案 0 :(得分:1)

(首先请参阅上面的说明。)

对于您将拥有的数据,通过配对连续的登录/注销对,您可以使用简单的 dateDiff([datepart],[date 1])处理数据以获取所需的信息如果你已经查询了数据,CF中的[日期2])功能可以找出差异。

对于数据处理,我建议在表中添加另一行 - 一行处理会话ID。这将确保您的登录/注销时间正确配对。然后,您可以设置类似以下内容的查询:

<cfquery name="getSession" datasource="[dsn]">
   SELECT DISTINCT sessionID
   FROM logTable
   WHERE userID = <cfqueryparam cfsqltype="cf_sql_integer" value="[inputted userID]" />
</cfquery>

...然后,为了获得各个登录会话的登录时间,运行这样的循环输出它们......

<cfoutput query="getSessions">
   <cfquery name="getSessionInfo" datasource="[dsn]">
      SELECT 
      (SELECT time 
         FROM logTable 
         WHERE sessionID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#getSessions.sessionID# />
         AND logType = <cfqueryparam cfsqltype="cf_sql_varchar" value="login" />)
      AS loginTime,
      (SELECT time 
         FROM logTable 
         WHERE sessionID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#getSessions.sessionID# />
         AND logType = <cfqueryparam cfsqltype="cf_sql_varchar" value="logout" />)
      AS logoutTime
      FROM logTable
   </cfquery>

   [ancillary output - use your DateDiff here with getSessionInfo.loginTime and getSessionInfo.logoutTime as your two date/times and use the data as you need]
</cfoutput>

我对此的SQL可能有些偏差,但至少它指出了你正确的方向...希望这有帮助...随时联系我列表以获得更多解释。

答案 1 :(得分:0)

在我目前的项目中,我正在使用“用户活动”的另一个定义。对我来说,这是会话明星和最后一页请求之间的时间段。我没有按照这种格式跟踪活动时间,但如果我需要 - 我会这样做。

会话开始时 - 在表sessions中创建可能如下所示的条目:

id (int) auto-incremented PK
sessionid (varchar) -- optional, session id string from ColdFusion
userid (int) FK
session_start (datetime) -- filled when created
last_request (datetime)

创建条目时,主键存储在用户会话中。

当用户发出请求时 - 更新last_request属性。

onSessionEnd被解雇时,也可以更新它,但你需要从当前时间减去会话超时以获得最后一个请求时刻 - 这使得这无用。

此方法的其他好处是您可以非常轻松地获得每个用户的聚合数据。例如,这将选择秒数(未测试,可能是错误的):

<cfquery datasource="mydsn" name="qGetUserData">
    select userid, sum(unix_timestamp(last_request) - unix_timestamp(session_start)) as timespan
    from sessions 
    group by userid
</cfquery>

按句点过滤也很容易 - 只需添加where session_start ...子句,对于特定用户的过滤也是如此。

答案 2 :(得分:0)

正如其他人所建议的那样,从长远来看,修改表结构是一种更好的方法。尝试配对日志记录(没有匹配的密钥)很困难,有时甚至是不可能的。略微修改的结构将更容易查询,并将产生更准确的结果。但是,如果您绝对无法修改表格,则可以计算粗略总计 - 如果您的记录ID是数字/顺序。

假设是“注销”记录总是在“登录”后插入。因此,注销的记录ID总是大于相应的“登录”。子查询可以将登录信息转换为成对:即当前和下一个登录记录。相应的“注销”记录ID将落在该范围内。匹配登录/注销后,使用日期/时间功能计算经过的时间(以分钟为单位)。然后按照您的意愿SUM()值并格式化结果。注意:显然,表格的正确索引是必须

那就是说,这种方法只提供估算。它有几个缺陷:

  • 某些数据库未进行优化 子查询非常好。即便如此 索引,查询性能可以 如果有很多,那就太穷了 涉及的数据。
  • 完全依赖于记录ID 用于识别。
  • 不考虑迷路退出 记录或错误/重复。所以 它可能不如其他人准确 方法
  • 需要比...更复杂的sql 替代结构

无论如何,我不确定我的MySQL语法。但是忽略MS Sql Server特定的功能,这应该是关闭的。 MS SQL中的性能与适当的索引相当,并且大约有100K记录。

SELECT  SUM(DateDiff(n, li.LogTime, lo.LogTime)) AS TotalTimeInMinutes
FROM    (
            SELECT  li.RecordID, li.UserID, li.LogType, li.LogTime,
                   (    SELECT MIN(t.RecordID) FROM  YourTable t
                        WHERE t.UserID   = li.UserID
                        AND   t.LogType  = li.logType
                        AND   t.RecordID > li.RecordID
                    ) AS NextRecordID
            FROM   YourTable li
            WHERE  li.UserID = 123
            AND    li.LogType = 'login'
        ) 
        li INNER JOIN YourTable lo ON lo.UserID = li.UserID
             AND lo.LogType = 'logout'
             AND lo.RecordID BETWEEN li.RecordID AND li.NextRecordID