我是Access的新手,并且正在使用Access 2007。
我正在对数据库进行简单查询,该数据库包含访问研讨会的客户列表。
我想向客户发送提醒,告知客户上次访问后3个月的服务时间。我创建了一个查询,以便能够返回从当月开始访问3个月的客户列表。例如,如果它现在是5月,则3个月前将是3月(包括5月)。
但是,3个月前访问过的客户可能在2个月前再次访问过。例如,客户A来自三月和四月。他的最后一次访问是在4月,因此,如果我在5月份进行查询,不应该出现在结果中,因为他的提醒应该只在6月发出。
我的查询已经解决了这个问题,但是它很慢。它在Access中加载需要一些时间。任何帮助都将在优化它时受到赞赏。
这里唯一重要的字段是Invoice.DebCode
,它是数据库中的customersID
。还有另一个表DEBTOR
,它是客户表及其详细信息。
我使用INNER JOIN,因为我需要在结果中显示客户(债务人)地址和详细信息。
SELECT Invoice.InvNo, Invoice.InvDate, Invoice.DebCode, Debtor.DebName, Debtor.AddL1, Debtor.AddL2, Debtor.AddL3, Invoice.CarNo, Invoice.ChaNo, Invoice.ExcReason
FROM Debtor
JOIN Invoice ON Debtor.DebCode = Invoice.DebCode
WHERE Year(InvDate) = Year(Now())
AND Month(InvDate) = Month(Now()) - 2
AND Invoice.DebCode NOT IN (SELECT Invoice.DebCode
FROM Invoice
WHERE Year(InvDate) = Year(Now())
AND ( (Month(InvDate) = Month(Now()) -1)
OR (Month(InvDate) = Month(Now())) )
答案 0 :(得分:3)
您可以通过调整WHERE子句来显着加快查询速度,以便直接针对日期字段进行比较(即,不通过Month()和Year()函数)。这样做可以让Jet引擎利用你在Invoice.InvDate字段上的索引(你确实将该字段编入索引,对吗?)。
SELECT I.InvNo, I.InvDate, I.DebCode, D.DebName, D.AddL1, D.AddL2, D.AddL3,
I.CarNo, I.ChaNo, I.ExcReason
FROM Debtor AS D
INNER JOIN Invoice AS I
ON D.DebCode = I.DebCode
WHERE I.InvDate Between DateSerial(Year(Now()), Month(Now()) - 2, 1)
And DateSerial(Year(Now()), Month(Now()) - 1, 0)
AND I.DebCode NOT IN
(SELECT Invoice.DebCode FROM Invoice
WHERE Invoice.InvDate > DateSerial(Year(Now()), Month(Now()) - 1, 0))
答案 1 :(得分:1)
如下:
SELECT a.debcode, a.debname, a.debstuff, b.most_recent AS last_over_three_months
FROM debtor AS a INNER JOIN
(
SELECT debcode, Max(invdate) AS most_recent
FROM invoice
GROUP BY debcode
)
as b
ON a.debcode= b.debcode
WHERE (month(now()) - Month(most_recent) >2);
你必须调整你的东西,但想法是一个子查询,选择最近的客户访问,然后从中只选择符合你的月标准的记录。
答案 2 :(得分:0)
由于mwolfe02的建议,我设法加快了查询速度。 为了存档和完成,我将在下面解释我的sql语句。
SELECT I.InvNo, I.InvDate, I.DebCode, D.DebName, D.AddL1, D.AddL2, D.AddL3,
I.CarNo, I.ChaNo, I.ExcReason
FROM Debtor AS D
INNER JOIN Invoice AS I
ON D.DebCode = I.DebCode
WHERE I.InvDate Between DateSerial(Year(Now()), Month(Now()) - 2, 1)
And DateSerial(Year(Now()), Month(Now())- 1, 0)
AND I.DebCode NOT IN
(SELECT Invoice.DebCode FROM Invoice
WHERE Invoice.InvDate Between DateSerial(Year(Now()), Month(Now()) - 1, 1)
And DateSerial(Year(Now()), Month(Now()), 0))
我编辑了底部子查询,因为mwolfe仅检查当月的客户。只有3个月前来的客户才有资格获得提醒。也就是说,他们不能在当月和前一个月之间访问过。
例如,客户A在4月和5月访问过。目前的月份是6月份,因此他没有资格获得提醒,因为他的最后一次访问是在5月。
客户B在4月和6月访问过,因此他没有资格获得提醒,因为他的最后一次访问是在6月。
因此,查询的英文版本将是:
从3个月前的当月最后一天开始收到来自当月和前一个月的客户。
我希望这可以帮助那些遇到同样问题的人。
正如darkjh和mikey建议的那样,我们可以“选择最近的客户访问,然后从中选择只符合您月份标准的记录。”
全部谢谢!