2013-03-07 104 views
0

我有发出自动续约通知到会员,其会员是关于基础上,他们购买了我们俱乐部的网上商店会员的最后日期到期,脚本:如何选择记录匹配的特定日期,但仅限于最近的记录不存在?

SELECT members.id, first, last, class, email, name AS membershipType, lifetime, store_transactions.dateModified FROM store_transactions 
LEFT JOIN members ON memberID = members.id 
WHERE 
(
DATE(store_transactions.dateModified) = SUBDATE(CURDATE(), INTERVAL 1 YEAR) 
/*AND 
NOT EXISTS(SELECT * FROM store_transactions WHERE DATE(store_transactions.dateModified) > SUBDATE(CURDATE(), INTERVAL 1 YEAR))*/ 
) 
AND categoryID = 1 AND lifetime != 'Y' 
GROUP BY members.id 
ORDER BY last, first 

我每天跑这个脚本通过一个CRON的工作,并且它运行良好(或者我认为)通过发送电子邮件给所有在一年前购买会员的会员。但是,我没有考虑到会员可以在我的脚本发出自动提醒之前更新其成员的事实)。

**更新: 在试图实施该解决方案的几个你推荐(THANK YOU!),这是我现在有我的查询:

SELECT members.id, first, last, class, email, name AS membershipType, lifetime, store_transactions.dateModified, categoryID FROM store_transactions 
LEFT JOIN members ON memberID = members.id 
GROUP BY members.id 
HAVING categoryID = 1 AND lifetime != 'Y' 
AND DATE(MAX(store_transactions.dateModified)) = '2012-03-24' /* specific date to simplify debugging */ 
ORDER BY last, first 

我觉得这是非常接近正确的解决方案,但GROUP BY往往会打破我的逻辑(这是我的头),因为我的store_transactions表具有不同类别的交易,可以由同一个成员(即会员,活动门票,广告,捐赠等)。为了这个查询的目的,我只关心查看成员类别事务(“categoryID = 1”)。额外的“lifetime!='Y'”禁止此查询返回其成员资格永不过期的终生成员。

总之,我希望此查询返回一年前拥有“categoryID = 1”事务的成员的记录,除非他们有“categoryID = 1”的更近期事务。下面是我的store_transactions表中的字段的情况下,它可以帮助:

ID 发票 MEMBERID 的categoryID 的productID 名 价格 数量 dateModified addedBy

+1

因此,如果有人做一个次要购买它将在同一个表中?然后你可以选择'MAX(store_transactions.dateModified)' – Horen 2013-03-07 22:17:14

+0

谢谢Horen。我相信你的提示很好,但我在执行时遇到问题(见下文)。另外,我会更新我的代码以显示最新内容。 – psterling 2013-03-17 15:31:02

回答

0

尝试检查MAX(store_transactions.dateModified)

SELECT members.id 
FROM store_transactions 
LEFT JOIN members ON memberID = members.id 
GROUP BY members.id 
HAVING DATE(MAX(store_transactions.dateModified)) > SUBDATE(CURDATE(), INTERVAL 1 YEAR) 

我简化了一下,但你应该得到正确的想法。

编辑:

您可以同时使用WHEREHAVING。在GROUP BY之前的地方,并过滤符合或不符合条件的单个行。具有条款包括对这些组的汇总。

SELECT members.id 
FROM store_transactions 
LEFT JOIN members ON memberID = members.id 
WHERE categoryID = 1 AND lifetime != 'Y' 
GROUP BY members.id 
HAVING DATE(MAX(store_transactions.dateModified)) > SUBDATE(CURDATE(), INTERVAL 1 YEAR) 
+0

谢谢你的帮助 - 我对我的延迟响应道歉!我觉得这几乎是我的正确解决方案,但是在HAVING之前(而不是在WHERE之后)放置GROUP BY members.id会破坏我的逻辑。虽然所有交易都记录在一张表中,但它们可以是不同的类别(会员可以在一次交易中购买会员资格,广告,活动门票等)。我只想看看'会员'交易,但通过在HAVING之前使用GROUP BY members.id,它忽略了每个会员不同类别的可能性。这是一个简单的修复? – psterling 2013-03-17 15:29:49

+0

检查我的答案中的编辑,我认为这是你想要的。 – JodyT 2013-03-17 16:58:42

+0

谢谢你JodyT!您的解决方案正是我所需要的 - 在此过程中我学到了一些新的MySQL技巧!我唯一需要改变的就是用'>'代替'=',这样它只会从一个日期返回结果。谢谢!!我会投你的答案,但我想我仍然有一个“坏”的声誉! – psterling 2013-03-17 23:13:16

0

也许类似

WHERE (0 in (SELECT COUNT(*) FROM store_transactions WHERE ...)) 

会工作?

+0

感谢您的建议。我会尝试,如果我不能让另一种方法工作... – psterling 2013-03-17 15:43:05

0

替代的想法,但我想我更喜欢JodyT的日期(MAX(dateModified))方法:

WHERE pk NOT IN (SELECT pk FROM store_transactions WHERE DATE(store_transactions.dateModified) > SUBDATE(CURDATE(), INTERVAL 1 YEAR)) 

(其中pk是你的桌子上一些独特的键)

+0

感谢您的建议。如果我无法让JodyT的方法工作,我会尝试... – psterling 2013-03-17 15:43:22