要使用 Access 查询完成您的任务,您需要创建一个名为 [Numbers] 的表,其中包含一个名为 [n] 的数字(长整数)列,其中包含数字 1、2、3、...,直到您期望的最高年份一起工作。我创建了我的如下
n
----
1
2
3
...
2499
2500
您还需要将以下 VBA 函数粘贴到访问模块中
Public Function IsValidDayOfYear(YearValue As Long, DayValue As Long) As Boolean
Dim IsLeapYear As Boolean
If (YearValue Mod 400) = 0 Then
IsLeapYear = True
ElseIf (YearValue Mod 100) = 0 Then
IsLeapYear = False
ElseIf (YearValue Mod 4) = 0 Then
IsLeapYear = True
Else
IsLeapYear = False
End If
IsValidDayOfYear = (DayValue <= IIf(IsLeapYear, 366, 365))
End Function
假设您的源表名为 [DateRanges]。我们将首先创建一个查询,该查询为源表中表示的每一年生成一年中的每一天。这里的诀窍是DateSerial()
“翻转”月份边界,所以
DateSerial(2013, 1, 32) = #2013-02-01#
和
DateSerial(2013, 1, 234) = #2013-08-22#
SELECT DateSerial(yr.n, 1, dy.n) AS [Date]
FROM Numbers yr, Numbers dy
WHERE
(
yr.n
BETWEEN (SELECT MIN(DatePart("yyyy", DateRanges.StartDate)) FROM DateRanges)
AND (SELECT MAX(DatePart("yyyy", DateRanges.EndDate)) FROM DateRanges)
)
AND (dy.n < 367) AND IsValidDayOfYear(yr.n, dy.n)
对于您的示例数据,该查询返回 2013 年的所有日期。
让我们将该查询保存为 [AllDays]。现在我们可以使用它来提取每个日期范围的各个日期(省略 StartDate 以便最终计数与您的问题相匹配)
SELECT [Date] FROM AllDays
WHERE EXISTS
(
SELECT * FROM DateRanges
WHERE AllDays.[Date] BETWEEN DateAdd("d", 1, DateRanges.StartDate) AND DateRanges.EndDate
)
返回对应于每个范围的各个日期,即
Date
----------
2013-04-14
2013-04-15
2013-04-18
2013-04-19
2013-04-20
2013-04-21
2013-04-22
2013-04-23
2013-04-24
2013-04-29
2013-04-30
2013-05-01
2013-05-02
2013-05-03
2013-05-06
2013-05-07
2013-05-08
2013-05-09
2013-05-10
我们可以将该查询保存为 [RangeDays],然后使用它按月计算我们的计数......
SELECT DatePart("m", [Date]) AS [Month], COUNT(*) AS NumOfDays
FROM RangeDays
GROUP BY DatePart("m", [Date])
...返回
Month NumOfDays
----- ---------
4 11
5 8