我的任务是发送电子邮件提醒我们的数据库中的客户通知他们的年度订阅即将到期。发送期限为帐户到期前30天,15天,7天。已发送的电子邮件将在下一个时间段之前重新发送(例如,john.doe @ aaa.com帐户即将于2012-06-01到期。服务器在2012-05-02发送电子邮件,然后等到2012-05 -17如果状态未改变则再次发送)。此外,如果account_status.statusId不是3,则服务器将不再发送消息并将account_metadata.v设置为7。
以下示例数据列表:
帐户
id email
1 velit@necenimNunc.com
2 nec@magna.org
3 imperdiet.ullamcorper.Duis@sagittisaugue.com
4 lacus@velitin.edu
5 Curae;@Phasellus.edu
6 dui.nec@Vivamussitamet.org
7 Aliquam.erat.volutpat@Intincidunt.com
8 vehicula.risus.Nulla@id.org
9 Fusce.diam.nunc@egetdictum.ca
10 urna@magnaNam.edu
11 vitae.erat@erategetipsum.ca
12 eu@eratneque.com
13 non@inconsectetuer.com
14 lectus@Nullamfeugiat.ca
15 sit.amet.diam@enimEtiamimperdiet.com
16 consectetuer.euismod.est@euerosNam.com
17 urna.Nunc.quis@egestas.com
18 tristique.aliquet.Phasellus@afelis.org
19 eget.tincidunt.dui@ligula.org
20 primis.in@accumsanneque.edu
21 ultricies.adipiscing@arcuVestibulum.com
22 euismod.et.commodo@nisi.edu
23 iaculis.quis@molestietortornibh.com
24 molestie@Pellentesque.org
25 ligula.tortor.dictum@dolor.com
26 dictum.ultricies.ligula@ipsum.com
27 pretium@turpis.ca
28 neque.Nullam.nisl@feugiatLoremipsum.edu
29 adipiscing.non.luctus@inconsequatenim.ca
30 faucibus@Mauris.com
ACCOUNT_STATUS
id statusId accountId time
1 1 2 2011-06-01 21:54:37
2 1 3 2011-06-02 09:07:14
3 1 4 2011-06-02 09:13:20
4 1 5 2011-06-02 09:54:44
5 1 6 2011-06-02 10:15:52
6 1 7 2011-06-02 10:17:22
7 2 7 2011-06-02 10:21:25
8 1 8 2011-06-02 11:09:03
9 1 9 2011-06-02 11:09:18
10 1 10 2011-06-02 11:13:29
11 1 11 2011-06-02 11:21:11
12 1 12 2011-06-02 11:21:35
13 3 5 2011-06-02 11:41:04
14 3 2 2011-06-02 11:46:07
15 1 13 2011-06-02 11:49:18
16 3 13 2011-06-02 11:53:45
17 1 14 2011-06-02 12:02:26
18 3 14 2011-06-02 12:10:54
19 1 15 2011-06-02 13:41:19
20 1 16 2011-06-02 15:27:03
21 3 16 2011-06-02 15:42:58
22 1 17 2011-06-02 15:46:05
23 1 18 2011-06-02 15:59:56
24 1 19 2011-06-02 16:13:41
25 1 20 2011-06-02 16:17:36
26 1 21 2011-06-02 16:47:04
27 1 22 2011-06-02 16:47:39
28 1 23 2011-06-02 18:35:29
29 1 24 2011-06-02 19:17:06
30 1 25 2011-06-02 20:07:33
account_metadata
id accountId k v
27033 2 remindEmail 3
27034 3 remindEmail 3
27035 4 remindEmail 3
27036 5 remindEmail 3
27037 6 remindEmail 3
27038 7 remindEmail 3
27039 8 remindEmail 3
27040 9 remindEmail 7
27041 10 remindEmail 7
27042 11 remindEmail 7
27043 12 remindEmail 7
27044 13 remindEmail 3
27045 14 remindEmail 3
27046 15 remindEmail 7
27047 16 remindEmail 3
27048 17 remindEmail 7
27049 18 remindEmail 7
请注意:
accounts.id
和account_metadata.accountId
是唯一的accounts.id = account_metadata.accountId = account_status.accountId
我目前的MySQL查询是:
如果account_status中的statusId不是3,则将remindEmail的值设置为7:
UPDATE `account_status` AS acs, `accounts` AS a, `account_metadata` AS am
SET am.v = '7'
WHERE acs.statusId != 3
AND acs.accountId = a.id
AND a.id = am.accountId
AND am.k = 'remindEmail';
已发送电子邮件提醒取决于1年前的期限(30天=> 7,15天=> 3,7天=> 1)和status = 3
:
SELECT am.accountId, a.email, am.k, am.v, acs.time
FROM accounts a
INNER JOIN account_status acs ON a.id = acs.accountId
INNER JOIN account_metadata am ON a.id = am.accountId
WHERE acs.statusId = 3
AND am.k = 'remindEmail'
AND NOW() <= DATE_ADD(acs.time, INTERVAL 365 DAY)
AND NOW() > DATE_ADD(acs.time, INTERVAL 365 - ((am.v & 1) * 7 + (am.v & 2) * 8 + (am.v & 4) * 15) DAY)
AND am.v = %s;
将account_metadata.v
更新为新状态:
UPDATE `account_metadata` AS am
SET am.v = '%s'
WHERE am.accountId = '%s'
AND am.k = 'remindEmail';
此处的问题是,account_status.accountId
并非唯一(请参阅上表accountId = 13
)。这将导致#1将某些行重置为7并且客户感觉他们被垃圾邮件发送。有没有办法修改#2和/或#1来选择最新的account_status.statusId
(基于account_status.time
)或更新最新的account_status.stautsId
?
答案 0 :(得分:0)
这似乎有效:
SELECT am.accountId, a.email, am.k, am.v, acs.time
FROM accounts a
INNER JOIN account_status acs ON a.id = acs.accountId
AND acs.id = (
SELECT acs2.id
FROM account_status acs2
WHERE acs2.time = (
SELECT MAX(acs3.time)
FROM account_status acs3
WHERE acs3.accountId = acs.accountId))
INNER JOIN account_metadata am ON a.id = am.accountId
WHERE acs.statusId = 3
AND am.k = 'remindEmail'
AND NOW() <= DATE_ADD(acs.time, INTERVAL 365 DAY)
AND NOW() > DATE_ADD(acs.time, INTERVAL 365 - ((am.v & 1) * 7 + (am.v & 2) * 8 + (am.v & 4) * 15) DAY)
AND am.v = %s;
答案 1 :(得分:0)
我最后自己解决了这个问题。
-- If statusId in account_status is not 3, then set value of remindEmail to 7 --
UPDATE account_metadata am
INNER JOIN (
SELECT acs0.id, acs0.accountId, acs0.statusId, acs0.time
FROM account_status acs0
CROSS JOIN (
SELECT accountId, MAX(id) AS id
FROM account_status
GROUP BY accountId
) acs1 USING (accountId, id)
WHERE acs0.statusId != 3
) acs2 ON am.accountId = acs2.accountId
SET am.v = '7'
WHERE am.k = 'remindEmail';
-- Have sent email reminder depend on the period --
-- (30 days => 7, 15 days => 3, 7 days => 1) before 1 year --
-- and status = 3 --
SELECT am.accountId, a.email, am.k, am.v, acs2.time
FROM accounts a
INNER JOIN (
SELECT acs.`id`, acs.`statusId`, acs.`accountId`, acs.`time`
FROM `account_status` acs
CROSS JOIN (
SELECT accountId, MAX(id) AS id
FROM `account_status`
GROUP BY accountId
) AS acs1
USING (accountId, id)
WHERE acs.`statusId` = 3
) acs2 ON a.id = acs2.accountId
INNER JOIN account_metadata am ON a.id = am.accountId
WHERE am.v = %s
AND am.k = 'remindEmail'
AND NOW() <= DATE_ADD(acs2.time, INTERVAL 365 DAY)
AND NOW() > DATE_ADD(acs2.time, INTERVAL 365 - ((am.v & 1) * 7 + (am.v & 2) * 8 + (am.v & 4) * 15) DAY);