#php #mysql #mysql-variables
#php #mysql #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, если самому новому значению cookie более 24 часов? Должен ли я попробовать установить и обновить дату через базу данных?
Предложения в качестве потенциальных решений для достижения этой цели — это то, что я ищу, имея в виду, что это приложение с очень интенсивным использованием базы данных, над которым я работаю, поэтому, чем меньше вызовов базы данных IMO, тем лучше.
Обновления
Итак, я пытаюсь спланировать это, используя базу данных, и я просто сталкиваюсь с проблемами со всех сторон.
Если я попытаюсь установить инкрементный столбец, невозможно определить, когда было последнее обновление.
Если я задаю таблицу, это ЧРЕЗВЫЧАЙНО сложно, поскольку мне приходится основывать значение на последовательных датах. Поэтому я не могу выполнить простой 7-дневный поиск, я должен проверить, что каждый результат находится в течение 24 часов после предыдущего результата, установленного в базе данных, иначе как бы я мог отличить кого-то, кто выполнил задачу в день 1, 3 и 7, от того, кто сделал это 1, 2, 3, 4, 5, 6 и 7.
Очистка базы данных не менее хлопотна. Как бы я сделал очистку. Я не могу просто проверить, что данные находятся в течение 7 дней с текущей даты, потому что это не учитывает, что кто-то выполняет задачи на 5-й день, но не на шестой день … а затем на 7-й день… и в равной степени это сложно, потому что у каждого пользователя будет разная дата начала. Итак, я, возможно, запустил задачи сегодня, а другой пользователь 5 дней назад. Я могу с уверенностью предположить, что все даты старше 7 дней истекли, но это на самом деле не помогает определять перерывы в днях.
Я так запутался, как на самом деле выполнить эту задачу.
Комментарии:
1. Я могу предложить схему немного позже, после того, как я сделаю несколько вещей, и вы внесете любые другие изменения. Но определите задачи, которые пользователь выполняет в этот промежуток времени, и если они фиксированы (этот список) на дату и время начала пользователя всего этого. Это действительно упрощенная модель
2. Задача является единственной. Я работаю над созданием системы бейджей для обмена трафиком. Я пытаюсь присвоить значок пользователю, если он посещал биржу в течение 7 дней подряд. Итак, задача — «загруженная пользователем страница surf.php «. Ни больше, ни меньше.
3. Хорошо, итак, у вас нет отдельной таблицы задач с идентификаторами и тому подобным
4. Нет, на самом деле я этого не делаю. Каждый раз, когда пользователь загружает surf.php «Счетчик кредитов» увеличивается (после завершения ввода капчи). Таким образом, на самом деле нет таблицы, которая бы подавала это вообще, хотя я мог бы легко это сделать.
5. Я
cookies
удалил тег. Вставьте его снова, если сочтете нужным
Ответ №1:
есть несколько способов сделать это.
если вы идете по маршруту db, у вас может быть ссылка из этой скрипки 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
, тогда вам нужно ее сбросить. преимущество этого маршрута, конечно, в отсутствии накладных расходов на БД, но в большом количестве «ручного труда».
Ответ №2:
Храните свои данные в базе данных, потому что проблемы с файлами 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. Проблема в том, что я не могу понять, как это сделать. lol Я продолжаю пытаться настроить план базы данных, и каждый раз возникают проблемы. Я не могу просто установить дату, потому что нет способа определить обновление даты по последнему обновлению даты. Поэтому мне пришлось бы хранить 7 дат. Тогда мне пришлось бы проверить последнюю дату на текущую дату. Если прошло более 24 часов, я должен сбросить все 7 дней ….. и это становится очень грязным и интенсивным использованием базы данных.
2. Это не будет беспорядочно, просто создайте имя столбца
created
в своей таблице и принимайте решения по запросам на основе этого столбца. Каждая строка будетDataTime
сохранена при каждой вставке, и вы можете выполнять запросы на основе этого.3. Аааа, я понимаю, о чем вы думаете. Таким образом, эффективно создавать таблицу, полностью предназначенную для хранения выполненных действий, в отличие от инкрементного столбца, в котором хранится количество действий. Затем сохраните время / дату для каждого действия и выполните действие на основе этого. Я мог бы сделать это таким образом, но все равно потребовалась бы огромная очистка каждый раз, когда есть перерыв в днях, чтобы удалить все предыдущие записи, поскольку нет необходимости вне этого конкретного действия для хранения этой информации.
4. к сожалению, его не так просто очистить, поскольку это многопользовательское приложение, поэтому у каждого пользователя будет свое время для оценки очистки. Я не могу проводить такую систематическую проверку. Я должен определить каждую дату для каждого пользователя, который старше текущей даты 24 часа тогда и только тогда, когда ее нет в последовательной строке других дат… что означает разрыв в датах.
5. Я собираюсь обновить вопрос, чтобы сделать некоторые из моих проблем более понятными.
Ответ №3:
Для нашего теста предполагается, что идентификатор страницы = 9 … это просматривается, считая значок (7 дней подряд для пользователя, видящего эту страницу). Этот факт был удален из комментариев op (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 (@ variables). Чтобы безопасно использовать переменные, нужно позаботиться о том, чтобы не предполагать, что какой-либо выходной столбец для выбора будет запущен раньше другого. Это факт, четко изложенный на странице руководства, озаглавленной «Определяемые пользователем переменные:
В следующем утверждении вы можете подумать, что MySQL сначала оценит @a, а затем выполнит присваивание вторым:
SELECT @a, @a:=@a 1, ...;
Однако порядок вычисления для выражений, включающих пользовательские переменные, не определен.
Тем не менее, мы знаем, что использование таких функций, как GREATEST(), LEAST() и COALESCE(), будет принудительно иметь более высокий приоритет.
Также бессмысленность в коде НАИБОЛЬШЕГО (N,-1) всегда будет возвращать N. Но нам нужно было принудительно установить приоритет этого столбца, вычисляемого перед
@prevDate:=DATE(viewDT) as dummy1
линия. Также см. Обязательное чтение книги Барона Шварца «Расширенные методы пользовательских переменных MySQL«.
Комментарии:
1. Это был бы правильный ответ, если бы я строго придерживался базы данных. Однако, поскольку я был открыт для способов сделать это…. Я не могу думать, что будет более быстрый метод, чем предложенный метод json. 0 подключений к базе данных. Очень легкие файлы на fs. Я могу обрабатывать пару миллионов ~ 1k файлов намного проще, чем десятки записей для миллионов пользователей в базе данных 🙂
2. Я думал, вы просили решение для БД, моя вина. Конечно, используйте свои собственные методы без БД и посмотрите, как вам это нравится