2013-06-28 38 views
1

我有一個下表如下如何查找給定範圍的缺失記錄?

Country Level  Code 
USA  Level A 10 
USA  Level A 11 
USA  Level A 12 
USA  Level A 13 
USA  Level A 14 
USA  Level B 20 
USA  Level B 21 
USA  Level B 22 
USA  Level B 23 
USA  Level B 24 

Level  Min Code  Max Code 
Level A 10   15 
Level B 20   25 

我需要找到如果表1具有所有在表2中所定義的範圍之間的代碼,如果一些東西丟失,我希望那個查詢的輸出。請幫助

在上面的例子中A級15,B級25的情況下,缺少

+0

在MS Access中沒有「創建序列」,因此您可能需要創建一個包含所有可能遇到的數字的表格,然後再與其對應。 – andreister

+0

如果你的表不止有幾千行,我建議**不要**在純(基於集合)的SQL中執行此操作。實現一個迭代第一個表的值並填充缺少記錄的表的vba函數會更有效率。 – Andreas

回答

2

這是一類的問題,可以用SQL訪問通過使用「數字表」來解決。此「數字表」是您在Access中手動創建的表格,其中包含一列數值(通常爲順序),其中包含您將使用的值的範圍。 (其他更復雜的SQL語言實現使我們能夠「即時」創建這種類型的表,但不幸的是,Access SQL不支持這種表,因此我們必須事先創建表,無論是手動還是通過一些VBA代碼)。

對於本示例,我們將使用名爲[Numbers]的表,其中一個名爲[n]的單個Number (Long Integer)字段。我們需要它來掩蓋[編號]值,10到25的整個預期範圍,所以我們的[數字]表看起來就像這樣:

n 
-- 
10 
11 
12 
... 
24 
25 

(請注意,它通常並不重要,如果一個「數字表「包含值以外的預期範圍,因爲使用它們的查詢通常會限制WHERE子句中值的範圍,但」數字表「完全覆蓋了的預期值範圍。)

一旦我們創建並填充了我們的[Numbers]表格,我們就可以從查詢

SELECT c.Country, c.Level, Numbers.n AS Code 
FROM 
Numbers, 
(SELECT DISTINCT [Country], [Level] FROM Codes) c 
INNER JOIN 
CodeRanges cr 
    ON c.Level=cr.Level 
WHERE Numbers.n BETWEEN cr.[Min Code] AND cr.[Max Code] 

返回規定範圍

Country Level Code 
------- ------- ---- 
USA  Level A 10 
USA  Level A 11 
USA  Level A 12 
USA  Level A 13 
USA  Level A 14 
USA  Level A 15 
USA  Level B 20 
USA  Level B 21 
USA  Level B 22 
USA  Level B 23 
USA  Level B 24 
USA  Level B 25 

之內的所有可能的代碼現在,我們可以通過使用上述的查詢作爲派生表找到在[代碼]表,從這個列表中缺少的項目(我將稱之爲 「AllCodes」):

SELECT [Country], [Level], [Code] 
FROM 
    (
     SELECT c.Country, c.Level, Numbers.n AS Code 
     FROM 
     Numbers, 
     (SELECT DISTINCT [Country], [Level] FROM Codes) c 
     INNER JOIN 
     CodeRanges cr 
      ON c.Level=cr.Level 
     WHERE Numbers.n BETWEEN cr.[Min Code] AND cr.[Max Code] 
    ) AllCodes 
WHERE NOT EXISTS 
    (
     SELECT * FROM Codes 
     WHERE Codes.Country=AllCodes.Country 
      AND Codes.Level=AllCodes.Level 
      AND Codes.Code=AllCodes.Code 
    ) 

返回

Country Level Code 
------- ------- ---- 
USA  Level A 15 
USA  Level B 25 
+0

是的,我知道但是,它是一個很長的名單,並有超過26000條記錄,並不斷更新每個月,難以維護和驗證,所以想保持簡單的範圍 – SSK

+0

@Sathish對不起,但我不明白你的評論。這個答案有問題嗎? –

+0

你的回答給了我正是我想要的,但是我需要創建一個所有的代碼而不是範圍的表。在我們的例子中,它的許多組合和更多代碼(aprox 26000)和增加 – SSK

1

生成缺少的代碼是一個真正的痛苦,尤其是在訪問。你需要一個所有可能的代碼列表,然後找到那些不在範圍內的代碼。在Access中生成這樣的列表並不是微不足道的。

要查找,如有丟失,你可以算:

select r.* 
from ranges r left join 
    (select level, count(distinct code) as NumCodes 
     from t 
    ) t 
    on r.level = t.level 
where t.NumCodes < (r.MaxCode - r.MinCode)+1