Php 计算连续访问的次数

Php 计算连续访问的次数,php,mysql,sql,Php,Mysql,Sql,每次登录用户访问网站时,他们的数据都会放入包含用户ID和日期的表中(每个用户每天一行或零行): 当我从主用户表中提取用户数据时,我需要随时访问连续访问的次数。。对于这个用户,它应该是4 目前,我正在通过主用户表中的非规范化连续访问计数器执行此操作,但由于未知原因,它有时会重置。。我想尝试一种只使用上表中数据的方法 获取该数字(上例中为4)的最佳SQL查询是什么?有数百名用户访问,我们每天有数百万注册用户和点击率 编辑:根据下面的评论,我正在发布我当前用于执行此操作的代码;然而,它有一个问题,它有

每次登录用户访问网站时,他们的数据都会放入包含用户ID和日期的表中(每个用户每天一行或零行):

当我从主用户表中提取用户数据时,我需要随时访问连续访问的次数。。对于这个用户,它应该是4

目前,我正在通过主用户表中的非规范化
连续访问
计数器执行此操作,但由于未知原因,它有时会重置。。我想尝试一种只使用上表中数据的方法

获取该数字(上例中为4)的最佳SQL查询是什么?有数百名用户访问,我们每天有数百万注册用户和点击率

编辑:根据下面的评论,我正在发布我当前用于执行此操作的代码;然而,它有一个问题,它有时会无缘无故地重置,而且它也会在周末为每个人重置它,很可能是因为DST更改

// Called every page load for logged in users
public static function OnVisit($user)
{
    $lastVisit = $user->GetLastVisit(); /* Timestamp; db server is on the same timezone as www server */
    if(!$lastVisit)
        $delta = 2;
    else
    {
        $today = date('Y/m/d');

        if(date('Y/m/d', $lastVisit) == $today)
            $delta = 0;
        else if(date('Y/m/d', $lastVisit + (24 * 60 * 60)) == $today)
            $delta = 1;
        else
            $delta = 2;
    }

    if(!$delta)
        return;

    $visits = $user->GetConsecutiveVisits();
    $userId = $user->GetId();

            /* NOTE: t_dailyvisit is the table I pasted above. The table is unused;
             * I added it only to ensure that the counter sometimes really resets
             * even if the user visits the website, and I could confirm that. */
    q_Query("INSERT IGNORE INTO `t_dailyvisit` (`user`, `date`) VALUES ($userId, CURDATE())", DB_DATABASE_COMMON);

    /* User skipped 1 or more days.. */
    if($delta > 1)
        $visits = 1;
    else if($delta == 1)
        $visits += 1;

    q_Query("UPDATE `t_user` SET `consecutivevisits` = $visits, `lastvisit` = CURDATE(), `nvotesday` = 0 WHERE `id` = $userId", DB_DATABASE_COMMON);
    $user->ForceCacheExpire();
}

如果没有必要记录用户登录webiste的每一天,而您只想知道他连续登录的天数,我更喜欢这种方式:

选择3列:LastVisite(日期)、ConcertiveDays(整数)和User

登录时,检查用户的条目,确定上次访问是否为“今日-1”,然后在“连续日”列中添加1,并在“上次访问”列中存储“今日”。如果最后一个vist大于“今天-1”,则在连续几天内存储1


HTH

如果不需要记录用户登录webiste的每一天,而您只想知道他连续登录的天数,我更喜欢这种方式:

选择3列:LastVisite(日期)、ConcertiveDays(整数)和User

登录时,检查用户的条目,确定上次访问是否为“今日-1”,然后在“连续日”列中添加1,并在“上次访问”列中存储“今日”。如果最后一个vist大于“今天-1”,则在连续几天内存储1


HTH

我错过了mysql标签,写了这个解决方案。遗憾的是,这在MySQL中不起作用,因为它不支持窗口功能

不管怎样,我还是把它贴了出来,因为我为此付出了一些努力。用PostgreSQL测试。与Oracle或SQL Server(或任何其他支持窗口功能的像样RDBMS)类似

测试设置 简单版本 输出:

   id   | max_consecutive_days
--------+----------------------
 444631 |                    4
更快/更短 后来我找到了一个更好的方法<代码>grp数字不是连续的(而是不断上升的)。没关系,因为这些只是达到目的的手段:

SELECT id, max(dur) + 1 AS max_consecutive_days
FROM (
    SELECT id, grp, max(visit) - min(visit) AS dur
    FROM (
      -- subtract an integer representing the number of day from the row_number()
      -- creates a "group number" (grp) for consecutive days
      SELECT id
            ,EXTRACT(epoch from visit)::int / 86400
           - row_number() OVER (PARTITION BY id ORDER BY visit) AS grp
            ,visit
      FROM   v
      ORDER  BY 1,2
      ) x
    GROUP BY 1,2
    ) y
GROUP  BY 1
ORDER  BY 1
LIMIT  1;

更多
  • 类似问题的解决方案。
    您可能能够在MySQL中实现类似的功能
  • 关于dba.SE的密切相关的答案,并有详细的解释和说明
  • 依此类推:

我错过了mysql标签,写下了这个解决方案。遗憾的是,这在MySQL中不起作用,因为它不支持窗口功能

不管怎样,我还是把它贴了出来,因为我为此付出了一些努力。用PostgreSQL测试。与Oracle或SQL Server(或任何其他支持窗口功能的像样RDBMS)类似

测试设置 简单版本 输出:

   id   | max_consecutive_days
--------+----------------------
 444631 |                    4
更快/更短 后来我找到了一个更好的方法<代码>grp数字不是连续的(而是不断上升的)。没关系,因为这些只是达到目的的手段:

SELECT id, max(dur) + 1 AS max_consecutive_days
FROM (
    SELECT id, grp, max(visit) - min(visit) AS dur
    FROM (
      -- subtract an integer representing the number of day from the row_number()
      -- creates a "group number" (grp) for consecutive days
      SELECT id
            ,EXTRACT(epoch from visit)::int / 86400
           - row_number() OVER (PARTITION BY id ORDER BY visit) AS grp
            ,visit
      FROM   v
      ORDER  BY 1,2
      ) x
    GROUP BY 1,2
    ) y
GROUP  BY 1
ORDER  BY 1
LIMIT  1;

更多
  • 类似问题的解决方案。
    您可能能够在MySQL中实现类似的功能
  • 关于dba.SE的密切相关的答案,并有详细的解释和说明
  • 依此类推:

是否可以将其更改为存储上次就诊日期、迄今为止的天数和最大连续天数?@xthexter:现在就是这样。。但我想把它改成这个系统,这样它就“防错”;每日就诊表已经存在一段时间了(但未使用)。很少,有时连续天数计数器会重置一个我无法复制的bug,而表中清楚地显示计数应该更高。因此,如果我使用表来存储数据,那么错误就不会再发生。一个更有效的解决方案是发布现有代码并修复它,而不是使用这种资源更密集的解决方案。是否可以将其更改为存储上次访问日期、到目前为止的天数和最大连续时间?@xthexder:现在就是这样。。但我想把它改成这个系统,这样它就“防错”;每日就诊表已经存在一段时间了(但未使用)。很少,有时连续天数计数器会重置一个我无法复制的bug,而表中清楚地显示计数应该更高。因此,如果我使用表来处理数据,那么bug就不会再发生了。一个更有效的解决方案是发布现有代码并修复它,而不是使用这个资源更密集的解决方案。
SELECT id, max(dur) + 1 AS max_consecutive_days
FROM (
    SELECT id, grp, max(visit) - min(visit) AS dur
    FROM (
      -- subtract an integer representing the number of day from the row_number()
      -- creates a "group number" (grp) for consecutive days
      SELECT id
            ,EXTRACT(epoch from visit)::int / 86400
           - row_number() OVER (PARTITION BY id ORDER BY visit) AS grp
            ,visit
      FROM   v
      ORDER  BY 1,2
      ) x
    GROUP BY 1,2
    ) y
GROUP  BY 1
ORDER  BY 1
LIMIT  1;