【问题标题】:MySQL Calculate Time OnlineMySQL在线计算时间
【发布时间】:2010-10-12 23:33:25
【问题描述】:

是否可以从类似的表格中计算在线时间

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 中做到这一点?

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

【问题讨论】:

  • 是否还有需要分组的用户 ID 字段?登录/注销是否仅包括日期或时间?
  • 是的,只是时间,还有一个用户字段,叫做用户。
  • 除了“服务器崩溃”之外,您还需要考虑一些事项。首先,我会假设您依赖用户从应用程序中物理注销,这在很多情况下可能不会发生。您可以在 application.cfc 中将注销作为 onSessionEnd() 方法的一部分处理,但唯一的处理方式是在会话到期时,根据应用程序的会话超时。
  • 假设所有这些,那么,您现在要处理实际数据...在这种情况下,假设服务器问题、基于会话的注销等 - 数据永远不会是完全准确的,在这种情况下,你试图用它来完成的事情是非常不可靠的。
  • 显然它只能精确到一个点。未注销的崩溃/用户是您始终必须考虑的问题。一个相关的问题是结果的用途是什么,您如何定义“在线时间”?聊天应用程序可能只需要知道自上次登录以来的在线时间。在这种情况下,在相对短暂的范围内跟踪数据,如“应用程序”可能是合适的。而工作应用程序可能需要跟踪“今天”在线时间。在这种情况下,数据库跟踪可能会更好。虽然有两列可能会使事情变得更容易,即 LoginTime、LogoutTime。

标签: mysql coldfusion time


【解决方案1】:

(请先看我上面的笔记。)

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

对于数据处理,我建议在您的表中添加另一行——用于处理会话 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 可能有点偏离,但至少它为您指明了正确的方向......希望这会有所帮助......请随时与我联系以获取更多解释。

【讨论】:

  • 没有。为查询中的每一行访问一次数据库在多个级别上都是不好的。几乎不需要在循环中查询。这通常表明您需要重新考虑方法..
  • 呃...有没有办法在没有额外行的情况下做到这一点?我很乐意在没有注销对的情况下丢弃登录行。
  • 如果您正在寻找单独的时间,那么您真的无能为力了。如果你正在寻找一个总时间,你总是可以使用 MySQL TIMEDIFF 并运行一个查询来返回每个时间的总和。这就是您要寻找的更多内容吗?
  • @Bubby4j - 你能回答第一篇文章中的问题吗?即这些信息是用来做什么的,有多少数量,等等?有不同的方法来处理它。但它会帮助我们知道这些问题的答案。
  • @Leigh ... 换句话说,我的意思是,对于每个单独的会话,您要么在 CF 中循环,要么在 SQL 中循环。在哪里进行处理并不重要,尽管 SQL 可能会更快地处理它。但是,除非您谈论的是数千个会话,否则处理时间可以忽略不计,尤其是当数据库在 localhost 上运行时。
【解决方案2】:

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

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

也就是说,此方法仅提供估计值。它有几个缺陷:

  • 某些数据库未优化 子查询很好。所以即使有 索引,查询性能可以 如果有很多,那就很穷 涉及的数据。
  • 仅依赖于记录 ID 用于识别。
  • 不考虑杂散注销 记录或错误/重复。所以 它可能不如其他准确 方法
  • 需要比 替代结构

无论如何,我不确定 MySQL 语法是什么。但是忽略 MS Sql Server 的特定功能,这应该是关闭的。 MS SQL 的性能不错,有适当的索引和大约 10 万条记录。

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

【讨论】:

    【解决方案3】:

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

    会话开始时 -- 在表 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 ... 子句,同样适用于按特定用户过滤。

    【讨论】:

      猜你喜欢
      • 2011-09-10
      • 2011-09-24
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      相关资源
      最近更新 更多