代码之家  ›  专栏  ›  技术社区  ›  sixtyfootersdude

MySQL:统计一个范围内的项目数

  •  3
  • sixtyfootersdude  · 技术社区  · 14 年前

    我正试图分析我的web服务器上的一些web日志。我把上周的所有日志都推到了一个mysql数据库中,我正在分析日志。

    我已经生成了一个表 sessionID 以及使用此mysql命令的会话长度:

    SELECT 
            Log_Analysis_RecordsToSesions.sessionID, 
            ABS(TIMEDIFF(
                    MIN(Log_Analysis_Records.date), 
                    MAX(Log_Analysis_Records.date)
            )) as session_length
    FROM 
            Log_Analysis_RecordsToSesions, 
            Log_Analysis_Records 
    WHERE 
            Log_Analysis_RecordsToSesions.recordID=Log_Analysis_Records.recordID 
    GROUP BY 
            sessionID;
    

    -

    +-----------+----------------+
    | sessionID | session_length |
    +-----------+----------------+
    |         1 |    2031.000000 | 
    |         2 |    1954.000000 | 
    |         3 |     401.000000 | 
    ...
    

    我现在要做的是修改语句,使其产生如下内容:

    Range (time)     Number of Sessions
    0 to 2           10
    2 to 4            4
    4 to 6           60
    ...
    

    该范围将是一个固定的时间量,我想计算在该范围内的会话数。我的第一个想法是使用php循环遍历所有内容,但这看起来非常耗时而且恶心。在mysql中有这样做的方法吗?

    3 回复  |  直到 14 年前
        1
  •  0
  •   greg0ire    14 年前

    我已经编辑了你的文章添加了一个别名,它使结果更可读。现在我想你可以试试这样的东西:

    SELECT 
            Log_Analysis_RecordsToSesions.sessionID, 
            ABS(TIMEDIFF(
                    MIN(Log_Analysis_Records.date), 
                    MAX(Log_Analysis_Records.date)
            )) as session_length,
            CONCAT(session_length DIV 2, ' to ', session_length DIV 2 + 2) as range
    FROM 
            Log_Analysis_RecordsToSesions, 
            Log_Analysis_Records 
    WHERE 
            Log_Analysis_RecordsToSesions.recordID=Log_Analysis_Records.recordID 
    GROUP BY 
             range
    ORDER BY session_length;
    
        2
  •  0
  •   True Soft    14 年前

    在生成的表上运行此查询:

    SELECT 
      CONCAT((session_length div 2000)*2, ' to ', ((session_length+2000) div 2000)*2) AS `Range (time)`, 
      COUNT(*) AS `Number of sessions` 
    FROM sessions 
    GROUP BY session_length div 2000
    
        3
  •  0
  •   Daniel Vassallo    14 年前

    您可能想创建另一个表,调用它 ranges :

    CREATE TABLE ranges (
       `range` int
    );
    
    INSERT INTO ranges VALUES (2), (4), (6), (8);
    

    然后,您可能希望将查询包装为派生表,并将 范围 带有派生表的表:

    SELECT   CONCAT(r.`range` - 2, ' to ', r.`range`) `range`,
             COUNT(session_length) number_of_sessions
    FROM     ranges r
    LEFT JOIN (
        SELECT    rs.sessionID, 
                  ABS(TIMEDIFF(MIN(ar.date), MAX(ar.date))) session_length
        FROM      Log_Analysis_RecordsToSesions rs, 
        JOIN      Log_Analysis_Records ar ON (rs.recordID = ar.recordID )
        GROUP BY  rs.sessionID;
    ) dt ON (dt.session_length > r.`range` - 2 AND 
             dt.session_length <= r.`range`)
    GROUP BY r.`range`;
    

    对于测试用例,让我们创建一个具有随机会话长度的虚拟表,如您的示例所示:

    CREATE TABLE sessions (
        session_id      int,
        session_length  int
    );
    
    INSERT INTO sessions VALUES (1, 2031);
    INSERT INTO sessions VALUES (2, 1954);
    INSERT INTO sessions VALUES (3, 401);
    INSERT INTO sessions VALUES (4, 7505);
    

    然后我们可以做以下工作,假设 范围 已创建表:

    SELECT   CONCAT(r.`range` - 2, ' to ', r.`range`) `range`,
             COUNT(session_length) number_of_sessions
    FROM     ranges r
    LEFT JOIN (
        SELECT session_id, session_length FROM sessions
    ) dt ON (dt.session_length / 1000 > r.`range` - 2 AND 
             dt.session_length / 1000 <= r.`range`)
    GROUP BY r.`range`;
    

    结果:

    +--------+--------------------+
    | range  | number_of_sessions |
    +--------+--------------------+
    | 0 to 2 |                  2 |
    | 2 to 4 |                  1 |
    | 4 to 6 |                  0 |
    | 6 to 8 |                  1 |
    +--------+--------------------+
    4 rows in set (0.00 sec)