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 缺失

4

2 回答 2

2

这是一类可以通过使用“数字表”通过 Access SQL 解决的问题。此“数字表”是您在 Access 中手动创建的表,其中包含一列数值(通常是连续的),涵盖您将使用的一系列值。

(SQL 语言的其他更复杂的实现允许我们“动态地”创建这种表,但不幸的是 Access SQL 不支持,所以我们必须事先手动或通过一些 VBA 代码创建表。)

对于本例,我们将使用一个名为 [Numbers] 的表,其中包含一个Number (Long Integer)名为 [n] 的字段。我们需要它覆盖整个预期的 [Code] 值范围,从 10 到 25,因此我们的 [Numbers] 表将如下所示:

 n
--
10
11
12
...
24
25

(请注意,“数字表”是否包含超出预期范围的值通常并不重要,因为使用它们的查询通常会在某个地方限制 W​​HERE 子句中的值范围,但“数字表”必须完全涵盖了预期的值范围。)

一旦我们创建并填充了我们的 [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”)来查找该列表中缺少的 [Codes] 表中的项目:

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
于 2013-06-28T15:27:19.623 回答
1

生成丢失的代码确实很痛苦,尤其是在 Access 中。您需要一个所有可能代码的列表,然后找到不在该范围内的代码。在 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
于 2013-06-28T14:17:17.990 回答