У меня нет кода или базы данных для отображения, потому что я нахожусь на стадии планирования, и я не могу найти правильный способ сделать это.
Я хочу определить, выполнял ли пользователь определенное действие каждый день в течение недели. Если они есть, я хочу выполнить действие. Каждый раз, когда есть перерыв в днях, мне нужно сбросить.
Так, например:
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 дней истекли, но это не помогает определить перерывы в днях.
Я так растерялся, как на самом деле выполнить эту задачу.
Есть несколько способов сделать это.
если вы идете по маршруту БД, вы можете получить ссылку из этого 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
, то вам нужно сбросить его. Преимущество этого маршрута, конечно, не накладные расходы, но много «ручного труда».
Храните ваши данные в базе данных, потому что проблемы с файлами 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
Один запрос может очистить ваши данные, что совсем не беспорядочно. Даже огромные базы данных обрабатываются так.
Для нашего теста это будет предполагать, что просматриваемая страница 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.