определить действия за период времени 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

echo ‘Вы успешно выполнили 71 задание подряд в течение 7 дней’;

Я думаю, что реальный вопрос становится, что было бы лучшим способом достичь этого? Должен ли я попытаться сохранить 7 cookie-файлов на основе даты и уничтожить все существующие cookie-файлы, если их новейшее значение имеет возраст более 24 часов? Стоит ли устанавливать и обновлять дату через базу данных?

То, что я ищу, — это потенциальные решения для достижения этой цели, учитывая, что это приложение с большой интенсивностью работы с базами данных, над которым я работаю, поэтому чем меньше база данных вызывает IMO, тем лучше.

ОБНОВЛЕНИЕ

Поэтому я пытаюсь спланировать это с помощью базы данных, и я просто сталкиваюсь с проблемами со всех сторон.

Если я попытаюсь установить инкрементный столбец, я не смогу узнать, когда было последнее обновление.

Если я установлю таблицу, она будет ОЧЕНЬ сложна, так как мне придется основывать значение на последовательных датах. Поэтому я не могу выполнить простой 7-дневный поиск, я должен проверить, что каждый результат находится в пределах 24 часов от предыдущего набора результатов в базе данных, иначе как я смогу отличить кого-то, кто выполнил задание в день 1, 3, и 7 против того, кто сделал это 1, 2, 3, 4, 5, 6 и 7.

Очистка базы данных в равной степени хлопотна. Как бы я сделал уборку. Я не могу просто проверить, что данные находятся в пределах 7 дней от текущей даты, потому что это не означает, что кто-то выполнил задачи на 5-й день, но не на 6-й день … и затем на 7-й день … и в равной степени это сложно, потому что у каждого пользователя будет своя дата начала. Таким образом, я, возможно, начал задачи сегодня и другой пользователь 5 дней назад. Я могу с уверенностью предположить, что все даты более 7 дней истекли, но это не помогает определить перерывы в днях.

Я так растерялся, как на самом деле выполнить эту задачу.

0

Решение

Есть несколько способов сделать это.

если вы идете по маршруту БД, вы можете получить ссылку из этого SQL скрипка

Я не знаю, насколько интенсивной была бы дБ, но я думаю, что это подытожит работу, необходимую, если вы идете по этому пути. Преимущество этого маршрута в том, что вам не нужно ничего удалять или сбрасывать, чтобы у вас были исторические данные, например, вы можете узнать, сколько «попыток» делает пользователь, изменив приведенный выше запрос на having count(distinct d) < 7 (будет возвращено столько строк, сколько пользователь попытался выполнить задачу)

Другой способ заключается в том, что вы можете использовать данные на основе файлов, такие как файл JSON на стороне сервера, для каждого пользователя, выполняющего задачи. с этим маршрутом вам нужно поддерживать данные самостоятельно, например, у вас есть простая структура JSON:

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

Что я имею в виду под сохранением данных самостоятельно, вы должны обновлять их каждый раз, когда применяются изменения, например, если текущая дата 2016-09-05 а также last_task является 2016-09-03, то вам нужно сбросить его. Преимущество этого маршрута, конечно, не накладные расходы, но много «ручного труда».

1

Другие решения

Храните ваши данные в базе данных, потому что проблемы с файлами 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

Один запрос может очистить ваши данные, что совсем не беспорядочно. Даже огромные базы данных обрабатываются так.

1

Для нашего теста это будет предполагать, что просматриваемая страница 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 просматривал страницу 9 по крайней мере 7 дней подряд (фактически 9 дней подряд). Этот пользователь получает значок в вашей системе.

Небольшая информация о переменной mysql (переменные @). Чтобы безопасно использовать переменные, нужно позаботиться о том, чтобы не предполагать, что любой выходной столбец для выбора будет срабатывать раньше другого. Этот факт четко изложен на странице руководства, озаглавленной Пользовательские переменные:

В следующем утверждении вы можете подумать, что MySQL будет оценивать
@a сначала, а затем выполнить назначение второго:

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

Однако порядок оценки для
выражения с участием пользовательских переменных не определены.

Тем не менее, мы знаем, что использование таких функций, как GREATEST (), LEAST () и COALESCE (), будет иметь более высокий приоритет.

Также ерунда в коде GREATEST (N, -1) всегда будет возвращать N. Но нам нужно было принудительно вычислить приоритет этого столбца перед

@prevDate:=DATE(viewDT) as dummy1

линия. Также см. Барона Шварца Обязательное чтение Продвинутые методы пользовательских переменных MySQL.

1
По вопросам рекламы [email protected]