这是一类可以通过使用“数字表”通过 Access SQL 解决的问题。此“数字表”是您在 Access 中手动创建的表,其中包含一列数值(通常是连续的),涵盖您将使用的一系列值。
(SQL 语言的其他更复杂的实现允许我们“动态地”创建这种表,但不幸的是 Access SQL 不支持,所以我们必须事先手动或通过一些 VBA 代码创建表。)
对于本例,我们将使用一个名为 [Numbers] 的表,其中包含一个Number (Long Integer)
名为 [n] 的字段。我们需要它覆盖整个预期的 [Code] 值范围,从 10 到 25,因此我们的 [Numbers] 表将如下所示:
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”)来查找该列表中缺少的 [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