在MySQL中按时间范围分组

时间:2012-07-23 14:26:03

标签: php mysql group-by

基础: 我有一个脚本,我的访客数量。一些有用的信息存储在MySQL数据库中。经过一年多的时间,我有超过180,000个数据记录,而且读取实际访问者的脚本非常慢。

我有这个脚本来计算访问者并检查它是否是同一个访问者或者是新访问者。为此,我有3个小时的时间范围,只有在此范围之后,访问将再次计算。

脚本:

$besucher_query = mysql_query('SELECT `time`, `agent` FROM `besucher` ORDER BY `ip` ASC');
while($besucher = mysql_fetch_array($besucher_query)) {
    $newtime = $besucher['time'];
    $newagent = $besucher['agent'];
    $limit = 3 /*std*/ * 60 /*min*/ * 60 /*sek*/; // three hours before same visitor counts again
    $diff = $newtime - $limit;

    if($oldtime <= $diff or ($oldtime > $diff and $newagent != $oldagent))
        $besucherzahl++;

    $oldtime = $besucher['time'];
    $oldagent = $besucher['agent'];
        }
$anzahl_besucher = $besucherzahl;
echo $anzahl_besucher;

几年前我创建了这个脚本,我知道这是最丑陋的方式。时间以UNIX时间戳格式存储。

现在我的问题: 如何直接在MySQL中将上述条件(3小时规则)“分组”?

2 个答案:

答案 0 :(得分:1)

您可以直接从PHP脚本执行以下查询,以获取过去3小时内的唯一身份访问者总数:

SELECT COUNT(DISTINCT `agent`) AS visitor_count
FROM `besucher`
WHERE `time` >= DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 3 HOUR);

答案 1 :(得分:0)

GROUP BY 10800*FLOOR(`time`/10800)

但是如果您在2:59和3:01有记录(比如说),这些记录将在输出中报告为2个单独的记录。如果要测量连续运行,那么您需要执行与当前代码类似的操作 - 但是您可以将结果存储在数据库中以便不再计算它们 - 只需添加一个新列,该列引用指定为的行会议开始时间:

ALTER TABLE besucher ADD COLUMN session_start INTEGER;

然后...

$limit = 3 /*std*/ * 60 /*min*/ * 60 /*sek*/;

$since=(integer)(file_get_contents('lastrun'))-$limit;
$besucher_query = mysql_query('SELECT 
      ip, `time`, `agent` FROM `besucher`
      WHERE `time`>$since 
      ORDER BY agent, ip, `time` ASC');
while($besucher = mysql_fetch_array($besucher_query)) {
   $newtime = $besucher['time'];
   $newagent = $besucher['agent'];
   $newip = $besucher['ip'];

   if ($newagent!=$oldagent 
       || $newip <> $oldip 
       || $newtime>$oldtime+$limit 
       || $newtime<$oldtime) {
     $sessionstart=$newtime;
   }
   $newagent=mysql_real_escape_string($newagent);
   mysql_query(
      "UPDATE besucher SET session_start=$sessionstart
       WHERE time=$newtime AND ip=$newip AND agent='$newagent'"
   );
   $oldtime = $besucher['time'];
   $oldagent = $besucher['agent'];
}
file_put_contents('lastrun', $oldtime);

然后你可以从(例如)....

获得会话数量
SELECT COUNT(*)
FROM 
(SELECT DISTINCT ip, agent, session_start
  FROM bessucher
  WHERE time BETWEEN $a AND $b) ilv

更简单的解决方案是在代码中使用会话管理并立即填充。