SQL на основе событий / времени и критериев

#mysql #sql

#mysql #sql

Вопрос:

Я думаю, это скорее вопрос шаблона проектирования, чем SQL.

В моем приложении пользователь может присоединиться, может создать магазин и загружать товары в свой магазин (допустим, есть пользователь, магазин (один к одному) и товары (многие к одному с магазинами).

Итак, я хочу иметь возможность выполнять определенные действия на основе времени и критериев (но только один раз), например, если через неделю после присоединения у пользователя нет магазина, я хочу отправить электронное письмо, или через 2 недели после присоединения к магазину, но товары не отправляются по электронной почте и т.д. — Но я хочу сделать это только один раз.

Это единственный запущенный один раз, который заставляет меня задуматься — так, например, допустим, у меня был этот запрос

 select * from user where joineddt < '1 week ago date'
  

И у меня был скрипт, который запускался каждые 3 часа, запускал SQL, а затем выполнял любое событие (например, отправлял электронное письмо) Затем я хочу убедиться, что если этот скрипт был запущен снова, он не заберет никаких пользователей, которые уже были обработаны. Я думал о введении таблицы «события», в которой после запуска события для пользователя регистрируется запись для этого события, но это снова, похоже, не работает. Например, скажем, у меня была таблица событий, был идентификатор, пользователь, событие

 select * from user a
left join event b on b.user = a.id
where a.joineddt < '1 week ago date'
and b.event = 'userjoined'
and b.id is null
  

Поэтому, когда в событиях нет записи, подходящей для события ‘userjoined’, оно не вернет результатов…Но на самом деле я хочу, чтобы он возвращал пользователей, у которых в таблице событий нет события для этого события ‘userjoined’?

Итак, кто-нибудь может придумать способ сделать то, что я предлагаю?

Ответ №1:

Ваш запрос всегда будет возвращать 0 строк, потому что если b.id равно нулю, b.событие никогда не может быть «подключено пользователем». Переместите критерии ‘userjoined’ в предложение join.

 SELECT a.* 
FROM user a 
LEFT JOIN event b ON (b.user = a.id AND b.event = 'userjoined') 
WHERE a.joineddt < '1 week ago date' 
AND b.id IS NULL
  

Ответ №2:

Вам не нужно иметь дополнительную таблицу (объединения стоят дорого) для реализации вашего решения. В вашей пользовательской таблице просто добавьте два столбца даты с возможностью обнуления: ‘date_joined’ и ‘reminded’. Убедитесь, что в логике вашего приложения (которую вы можете определить на стороне таблицы / базы данных) значение ‘date_joined’ по умолчанию соответствует дате присоединения, а значение ‘reminded’ равно НУЛЮ.

Чтобы забрать пользователей, нуждающихся в напоминании:

 SELECT * FROM users
WHERE date_joined > '1 week ago' AND reminded IS NULL
  

Обязательно заполните поле «напомнено» с указанием даты после отправки электронного письма. Таким образом, следующий запуск скрипта не обнаружит это.

Комментарии:

1. Эти 2 события были просто примером, событий много, и я хотел бы добавить больше с течением времени, не хотел бы добавлять столбцы для каждого типа события. С точки зрения затрат, это будет периодически запускаемый автономный демон, поэтому это не должно повлиять.