簡體   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