2010-11-14 76 views
3

我试图从我的网络服务器分析一些网络日志。我把上周的所有日志都放到了mysql数据库中,我正在分析这些日志。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中做到这一点?

回答

0

我编辑了你的帖子来添加一个别名,它使结果更具可读性。现在,我想你可以尝试这样的事:

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; 
0

您可能希望创建另一个表,并称其ranges

CREATE TABLE ranges (
    `range` int 
); 

INSERT INTO ranges VALUES (2), (4), (6), (8); 

那么你可能要包装你的查询作为派生表,和左加入ranges表派生表:

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); 

然后我们可以做到以下几点,假设ranges表已创建:

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) 
0

运行此查询过您生成的表格:

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 
+0

你能解释一下wh在第二行是干什么的? – sixtyfootersdude 2010-11-15 09:48:35

+0

它将'group by'中使用的显示值与''to''和'group by'中使用的下一个组合(+ 2000ms)连接起来。 '* 2'用于显示:因为,例如,401和1500 div 2000是'0'(group by中使用的值),2031 div 2000是'1' - 另一个组。 – 2010-11-16 04:59:12