2011-06-03 66 views
3

我可以加快Ms Access 2007上的这个声明吗?查找丢失的钥匙

SELECT * 
FROM (SELECT DISTINCT p.zipcode, p.place FROM p) AS tmp 
WHERE NOT EXISTS 
    (SELECT * FROM zipcodes WHERE 
    (tmp.zipcode=zipcodes.zipcode) AND (tmp.place=zipcodes.place)); 

我想找到(邮编,地点)在p表不在zipcodes表的组合。

p表格比较大,但是当缩小到tmp时有大约40.000个条目。 zipcodes表有大约15.000个条目。 zipcodes表被编入索引(邮编,地点)。

它需要一个多小时才能得到我的结果。我能更快得到它吗?我可以在Access 2007中看到执行计划吗? (我不是普通的Access用户,也不是SQL专家。)

亲切的问候, Karsten。

+0

没有理由在返回NULL时做'NOT EXISTS(SELECT * ...)'应该做同样的事情(你只是检查是否存在匹配的行,存储在行中的实际数据最终是不相关的) – 2011-06-03 14:32:57

+0

我是否正确理解我可以放弃EXISTS关键字,即'WHERE NOT(SELECT *)...'? – 2011-06-03 14:49:00

+1

不,您需要存在'关键字,但您的'select'语句可以简单地'select null'而不是'select *',因为你实际上并不关心行中的数据是什么,只有没有行符合你的条件。 – 2011-06-03 14:54:16

回答

5

您可以左键联接两个表并从结果集中排除匹配的行。通过邮政编码和地点索引邮政编码表,这可能比现在快得多。希望足够快,你不需要创建一个中间临时表。

SELECT DISTINCT p.zipcode, p.place 
FROM p LEFT JOIN zipcodes AS z ON (p.place = z.place) AND (p.zipcode = z.zipcode) 
WHERE (((z.zipcode) Is Null)); 

编辑:你要见的执行计划。从TechRepublic上的这篇文章开始:Use Microsoft Jet's ShowPlan to write more efficient queries您也可以通过在网上搜索“Jet ShowPlan”找到更多信息。

+0

这是非常快,在我看来,最优雅。谢谢! – 2011-06-03 15:47:59

+0

JOIN始终优于NON IN或NOT EXISTS,因为在Jet/ACE中,JOIN始终在比较的两侧使用索引,而有时使用NOT则仅在一侧使用它。坦率地说,当我需要一个可编辑的记录集时,我只使用子查询 - 否则我将使用JOIN。 – 2011-06-09 01:54:58

1

首先,我将创建一个'真正'表tmp而不是以这种方式使用它。这本身可能已经帮助(不确定)。其次,我会确保p表中的邮政编码有索引,如果没有帮助,也可以在表tmp。如果这仍然没有帮助,请在zipcodes上的(邮编,地点)组合上创建索引。

+0

没错。使用真正的表格可以大大提高查询速度(<10秒)。谢谢! – 2011-06-03 15:43:42