繁体   English   中英

确定一段时间内的操作PHP MySQL

[英]determine actions over period of time PHP MySQL

我没有任何代码或数据库可显示,因为我正处于计划阶段,因此我无法找出正确的方法来执行此操作。

我想确定用户是否在一周的时间内每天都执行了特定的操作。 如果他们有,我想执行一个动作。 每次有几天的休息时间,我都需要重新设置。

因此,例如:

Day 1 | task performed 25 times
Day 2 | task performed 13 times
Day 3 | task performed 18 times
Day 4 | task not performed... start over at Day 1.
.....
Day 1 | task performed 3 times
Day 2 | task performed 11 times
Day 3 | task performed 14 times
Day 4 | task performed 7 times
Day 5 | task performed 3 times 
Day 6 | task performed 10 times
Day 7 | task performed 23 times

回显“您在7天内连续成功完成了71个任务”;

我想真正的问题是,实现这一目标的最佳方法是什么? 我是否应该尝试根据日期存储7个cookie,如果最新的cookie值超过24小时,则应销毁所有现有的cookie? 我应该尝试通过数据库设置和更新日期吗?

我正在寻找作为实现此目标的潜在解决方案的建议,请记住,这是我正在研究的数据库密集型应用程序,因此数据库调用IMO越少越好。

更新

因此,我正在尝试使用数据库进行规划,而我只是在各个角度遇到问题。

如果我尝试设置增量列,则无法得知上次更新的时间。

如果我设置了表格,则其极端复杂,因为我必须根据连续日期来设置值。 因此,我无法进行简单的7天搜索,我必须测试每个结果是否在数据库中先前结果集的24小时内,否则我将如何区分在第1、3,和7比1、2、3、4、5、6和7。

清理数据库同样麻烦。 我将如何进行清理。 我不能简单地测试数据是否在当前日期的7天内,因为这不能说明某人在第5天而不是在第六天完成任务……然后在第七天……而且同样复杂,因为每个用户都有不同的开始日期。 因此,我今天可能开始工作,而5天前又有另一个用户。 我可以放心地假设7天以上的所有日期都已过期,但这并不能真正确定几天内的休息时间。

我很困惑如何实际完成这项任务。

将您的数据保存在数据库中,因为cookie的问题在于用户可以随时清洁其浏览器。 您可以随时处理数据库中的数据。

假设您将这种格式的数据保存在数据库中:

Description | task_id | created 
Task perfor. | 2      | 2016-10-17
Task perfor. | 2      | 2016-10-17
Task perfor. | 2      | 2016-10-18
Task perfor. | 2      | 2016-10-18

您只需运行查询即可删除数据:

delete from table where created = date

一个查询可以清理您的数据,一点也不麻烦。 即使是巨大的数据库也是这样处理的。

有几种方法可以做到这一点。

如果要使用数据库路由,则可以从此SQL提琴中获取参考

我不知道数据库的密集程度,但是我认为如果您走这条路线,那将总结所需的工作。 此路由的优点是您不必删除或重置任何内容,因此您将拥有历史数据,例如,通过将上述查询更改having count(distinct d) < 7 (它可以获取用户多少次“尝试”将返回与用户尝试完成任务一样多的行)

另一种方法是您可以使用基于文件的数据,例如在服务器端为执行任务的每个用户使用JSON文件。 使用此路由,您需要自己维护数据,例如,您具有以下简单的JSON结构:

{
   "day1": "2016-09-01",
   "last_task": "2016-09-03",
   "accumulated_task": "56"
}

我自己指的是维护数据,这是您每次应用更改时都需要对其进行更新,例如当前日期为2016-09-05last_task2016-09-03 ,则需要将其重置。 该路由的优点当然是没有数据库开销,但是有很多“体力劳动”。

对于我们的测试,这将假定已查看页面ID = 9 ...,并计入一个徽章(用户连续7天看到该页面)。 这个事实已被排除在操作评论之外(7天和徽章)。 至于第9页,我们只是在此答案中加以说明。

因此,如果用户连续7天查看该页面,我们希望该用户出现在输出中。 注意,页码是9。

架构和数据加载

create schema db40076704;
use db40076704;

create table pageViews
(   id int auto_increment primary key,
    userId int not null,
    viewDT datetime not null,
    pageId int not null
    -- include decent index choices here
    -- include Foreign Key constraints here
);
truncate pageViews;
insert pageViews (userId,viewDT,pageId) values
(101,'2016-09-05 21:00:00',9),
(101,'2016-09-06 11:00:00',9),
(101,'2016-09-06 15:55:00',9),
(101,'2016-09-06 15:57:00',9),
(101,'2016-09-07 21:00:00',9),
(101,'2016-09-08 21:00:00',999999),
(101,'2016-09-09 21:00:00',9),
(101,'2016-09-10 21:00:00',9),
(101,'2016-09-11 21:00:00',9),

(150,'2016-09-01 21:00:00',9),
(150,'2016-09-06 11:00:00',9),
(150,'2016-09-06 15:55:00',9),
(150,'2016-09-06 15:57:00',9),
(150,'2016-09-07 21:00:00',9),
(150,'2016-09-08 10:44:00',9),
(150,'2016-09-09 21:00:00',9),
(150,'2016-09-10 21:00:00',9),
(150,'2016-09-11 23:00:00',9),
(150,'2016-09-12 23:00:00',9),

(200,'2016-09-08 10:44:00',9),
(200,'2016-09-10 21:00:00',9),
(200,'2016-09-12 21:00:00',9),
(200,'2016-09-14 23:00:00',9),
(200,'2016-09-16 23:00:00',9),
(200,'2016-09-18 23:00:00',9),
(200,'2016-09-20 23:00:00',9);

内部查询显示详细信息以进行调试

select userId, 
date(viewDT), 
    (@rn := if(@curUser = userId 
            AND (@prevDate=DATE(viewDT) OR @prevDate=DATE_SUB(DATE(viewDT),INTERVAL 1 DAY)), @rn, 
                if(@curUser := GREATEST(userId,-1), @rn+1, @rn+1) 
            ) 
    ) rn, 
@prevDate:=DATE(viewDT) as dummy1 
from pageViews 
join (select @curUser:=-1,@prevDate:='',@rn:=0) params 
where pageId=9 
order by userId,viewDt;
+--------+--------------+------+------------+
| userId | date(viewDT) | rn   | dummy1     |
+--------+--------------+------+------------+
|    101 | 2016-09-05   | 1    | 2016-09-05 |
|    101 | 2016-09-06   | 1    | 2016-09-06 |
|    101 | 2016-09-06   | 1    | 2016-09-06 |
|    101 | 2016-09-06   | 1    | 2016-09-06 |
|    101 | 2016-09-07   | 1    | 2016-09-07 |
|    101 | 2016-09-09   | 2    | 2016-09-09 |
|    101 | 2016-09-10   | 2    | 2016-09-10 |
|    101 | 2016-09-11   | 2    | 2016-09-11 |
|    150 | 2016-09-01   | 3    | 2016-09-01 |
|    150 | 2016-09-06   | 4    | 2016-09-06 |
|    150 | 2016-09-06   | 4    | 2016-09-06 |
|    150 | 2016-09-06   | 4    | 2016-09-06 |
|    150 | 2016-09-07   | 4    | 2016-09-07 |
|    150 | 2016-09-08   | 4    | 2016-09-08 |
|    150 | 2016-09-09   | 4    | 2016-09-09 |
|    150 | 2016-09-10   | 4    | 2016-09-10 |
|    150 | 2016-09-11   | 4    | 2016-09-11 |
|    150 | 2016-09-12   | 4    | 2016-09-12 |
|    200 | 2016-09-08   | 5    | 2016-09-08 |
|    200 | 2016-09-10   | 6    | 2016-09-10 |
|    200 | 2016-09-12   | 7    | 2016-09-12 |
|    200 | 2016-09-14   | 8    | 2016-09-14 |
|    200 | 2016-09-16   | 9    | 2016-09-16 |
|    200 | 2016-09-18   | 10   | 2016-09-18 |
|    200 | 2016-09-20   | 11   | 2016-09-20 |
+--------+--------------+------+------------+
25 rows in set (0.00 sec)

使用以上的最终答案

SELECT userId,rn,count(*) days_In_A_Row 
from 
(   SELECT userId, 
    DATE(viewDT), 
        (@rn := if(@curUser = userId 
                AND (@prevDate=DATE(viewDT) OR @prevDate=DATE_SUB(DATE(viewDT),INTERVAL 1 DAY)), @rn, 
                    if(@curUser := GREATEST(userId,-1), @rn+1, @rn+1) 
                ) 
        ) rn, 
    @prevDate:=DATE(viewDT) as dummy1 
    FROM pageViews 
    JOIN (SELECT @curUser:=-1,@prevDate:='',@rn:=0) params 
    WHERE pageId=9 
    ORDER BY userId,viewDt 
) xDerived 
GROUP BY userId,rn 
HAVING days_In_A_Row>6; 

+--------+------+---------------+
| userId | rn   | days_In_A_Row |
+--------+------+---------------+
|    150 | 4    |             9 |
+--------+------+---------------+

因此,用户150至少连续7天(实际上是连续9天)浏览了第9页。 该用户在您的系统中获得了徽章。

有关mysql变量(@变量)的一些信息。 为了安全地使用变量,必须注意不要假设某个选择的任何输出列都将在另一个之前触发。 这在名为“ 用户定义的变量 ”的手册页中有明确说明:

在下面的语句中,您可能认为MySQL将首先评估@a,然后再进行赋值:

SELECT @a, @a:=@a+1, ...;

但是,涉及用户变量的表达式的求值顺序是不确定的。

就是说,我们知道使用GREATEST(),LEAST()和COALESCE()之类的函数将被强制具有更高的优先级。

同样,GREATEST(N,-1)代码中的废话将始终返回N。但是我们需要强制在计算列之前优先计算

@prevDate:=DATE(viewDT) as dummy1 

线。 另请参阅Baron Schwartz的《 必读的 高级MySQL用户变量技术》

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM