2011-06-03 102 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