在 SQL "select" 查询中定义临时 table

Define a temporary table within an SQL "select" query

我指的是 MS Access SQL。假设我有一列包含人口的出生日期和这些日期所属的几十年。

Year Decade
1971 8
1953 6
1958 6
1929 3
1930 4

我想创建一个查询来显示一个世纪的每个十年有多少人出生。

我知道会是这样的

SELECT (Year mod 100) \ 10 + 1 as [Decade], Count(*) as [How many people]
FROM People
GROUP BY (Year mod 100) \ 10 + 1

我的问题是,可能有几十年我的人口中没有人出生,但我仍然希望这些在我的查询中显示为零。

我理想的解决方案是动态定义一个 table,由行 {1,2,3,4...} 组成,就像您在任何编程语言中所做的那样,例如 Python decades = range(1,10),然后用计数的人创建 table,然后用 left join.

将这两个连接在一起

这似乎不可能,但我是 SQL 和数据库的新手。那可能吗?还有哪些其他方法?

MsAccess 没有像 Range() 这样的函数可供您使用。我在我的数据库中所做的是创建一个 table 数字以用于此类情况。

创建此 table 的最简单方法是使用 Excel 电子表格构建数字列(例如,从 1 到 1,000),然后将电子表格导入为新的 table。然后进行任何适当的调整——例如,新的 table 应该在数字列上有一个主键,并且数字列可能应该是长整型数据类型。您可以调用 table [Numbers] 并将该列命名为 [NumberValue] - 这些名称已经存在(您可以轻松地将您的列命名为 [Nums] 甚至只是 [N])。但我会警告不要将名称 [Number] 用于 table 或列,因为 Number 是一种数据类型名称,而 MSAccess 并不总是能很好地处理 SQL 或 VBA 关键字的名称。

现在您可以将新 table 与常规 sql 一起使用:Select * from [Numbers] where NumberValue >= 1 and NumberValue <= 10

首先,创建一个小查询来生成数字:

Select Distinct Abs([id] Mod 10) As N
From MSysObjects;

保存为十。

然后创建一个 Cartesian(乘法)查询,如下所示:

Select 
    Ten.N As Decade, 
    Val(Nz(T.C)) As [How many people]
From 
    Ten
Left Join
    (Select Count(*) As C, [Year] Mod 10 As D
    From People
    Group By [Year] Mod 10) As T
    On Ten.N = T.D

输出类似于:

returns 今年日期的扩展示例:

SELECT 
    DateSerial(Year(Date()),1,1+[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100) AS [Date]
FROM 
    Ten AS Ten_0, 
    Ten AS Ten_1, 
    Ten AS Ten_2
WHERE 
    (((DateSerial(Year(Date()),1,1+[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100))<=DateSerial(Year(Date()),12,31)) 
    AND 
    ((Ten_2.N)<4))
ORDER BY 
    DateSerial(Year(Date()),1,1+[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100);