在某些情况下,“日期表”可以辅助日期操作。与“数字表”类似,“日期表”是一个表格,其中包含给定范围内每个日期的一行,通常涵盖实际数据中可能遇到的整个日期范围。
对于名为 [SampleData] 的表中的样本数据
Row StartDate EndDate
--- ---------- ----------
001 2010-01-02 2012-02-04
002 2010-01-02 2010-01-05
003 2010-04-02 2010-05-05
004 2010-01-02 2012-02-04
005 2012-02-02 2012-02-03
还有一个简单的 [DatesTable]
theDate
----------
2010-01-01
2010-01-02
2010-01-03
...
2012-12-30
2012-12-31
查询
SELECT
sd.Row,
dt.theDate,
Year(dt.theDate) AS theYear,
Month(dt.theDate) AS theMonth
FROM
SampleData AS sd
INNER JOIN
DatesTable AS dt
ON dt.theDate >= sd.StartDate
AND dt.theDate <= sd.EndDate
为每个 [SampleData].[Row] 值的间隔中的每个日期返回一行。 (对于这个特定的样本数据,总共有 1568 行。)
对其进行聚合
SELECT
Row,
theYear,
theMonth,
COUNT(*) AS NumberOfDays
FROM
(
SELECT
sd.Row,
dt.theDate,
Year(dt.theDate) AS theYear,
Month(dt.theDate) AS theMonth
FROM
SampleData AS sd
INNER JOIN
DatesTable AS dt
ON dt.theDate >= sd.StartDate
AND dt.theDate <= sd.EndDate
) AS allDates
GROUP BY
Row,
theYear,
theMonth
给我们所有的计数
Row theYear theMonth NumberOfDays
--- ------- -------- ------------
001 2010 1 30
001 2010 2 28
001 2010 3 31
001 2010 4 30
001 2010 5 31
001 2010 6 30
001 2010 7 31
001 2010 8 31
001 2010 9 30
001 2010 10 31
001 2010 11 30
001 2010 12 31
001 2011 1 31
001 2011 2 28
001 2011 3 31
001 2011 4 30
001 2011 5 31
001 2011 6 30
001 2011 7 31
001 2011 8 31
001 2011 9 30
001 2011 10 31
001 2011 11 30
001 2011 12 31
001 2012 1 31
001 2012 2 4
002 2010 1 4
003 2010 4 29
003 2010 5 5
004 2010 1 30
004 2010 2 28
004 2010 3 31
004 2010 4 30
004 2010 5 31
004 2010 6 30
004 2010 7 31
004 2010 8 31
004 2010 9 30
004 2010 10 31
004 2010 11 30
004 2010 12 31
004 2011 1 31
004 2011 2 28
004 2011 3 31
004 2011 4 30
004 2011 5 31
004 2011 6 30
004 2011 7 31
004 2011 8 31
004 2011 9 30
004 2011 10 31
004 2011 11 30
004 2011 12 31
004 2012 1 31
004 2012 2 4
005 2012 2 2
然后我们可以对此进行报告,或交叉表,或做任何其他有趣的事情。
旁注:
“日期表”非常有用的一种情况是当我们必须处理法定假日时。那是因为
有时,法定假日的“休息日”并不是实际的一天。如果“国际培根日”是在周日,那么我们可能会在周一放假。
一些法定假日可能难以计算。例如,对我们加拿大人来说,耶稣受难日是(如果我没记错的话)“春分后第一个满月后第一个星期日之前的星期五”。
如果我们有一个“日期表”,那么我们可以添加一个 [StatutoryHoliday] Yes/No 字段来标记所有(观察到的)假期,然后使用 ... WHERE NOT StatutoryHoliday 排除它们。