在 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);
我指的是 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);