【问题标题】:MS Access crosstab queries when raw data holds date ranges原始数据包含日期范围时的 MS Access 交叉表查询
【发布时间】:2016-11-23 16:18:12
【问题描述】:

我有最近美国总统的下表:

ID President StartDate  EndDate
1  Bush Sr.  20-Jan-89  20-Jan-93
2  Clinton   20-Jan-93  20-Jan-01
3  Bush Jr.  20-Jan-01  20-Jan-09
4  Obama     20-Jan-09  20-Jan-17
5  Trump     20-Jan-17  20-Jan-21

要注意的关键是,总统是按时间间隔给出的,有开始日期和结束日期。

我现在想要交叉表,其中列是某个时间间隔(年、季度或月),行是不同的总统,值是 1 或 0,具体取决于总统是否在给定时间间隔内任职。

更一般地说,我希望我的数据表中的行匹配交叉表查询中的几个可能的列,而不仅仅是一个。到目前为止,我只看到了相反的交叉表示例,其中多个数据值映射到同一个交叉表列。

我希望生成的表格如下(由于篇幅限制,仅显示 1993-2001 年):

          1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001…
Bush Sr.    1    1    1    1    1    0    0    0    0    0    0    0    0
Clinton     0    0    0    0    1    1    1    1    1    1    1    1    1
Bush Jr.    0    0    0    0    0    0    0    0    0    0    0    0    1
…

请让我知道这是否有意义,或者我是否应该进一步详细说明。

【问题讨论】:

  • 请编辑您的问题并添加预期结果
  • 感谢 Sami,我添加了一个包含所需结果的表格。

标签: sql ms-access ms-access-2010


【解决方案1】:

您要查找的字段如下所示:

IIf(MyYear BETWEEN Year(StartDate) AND Year(EndDate),1,0)

【讨论】:

  • 谢谢,您的代码将返回 1 或 0,具体取决于变量 MyYear 是否介于两个日期值之间。但我不确定这是否会奏效,因为我正在尝试构建交叉表查询,除非我在这里遗漏了一些东西......
  • 您可以在 SELECT 查询中使用它,然后将其用作交叉表查询的基础。
【解决方案2】:

考虑填充一个单独的 DateRange 表,该表包含所有范围值,包括有序 Years、Quarters 和 Months .您可以在 VBA 中使用动态 SQL 查询构建这样的表:

Public Sub PopulateTime()
    Dim i As Integer, j As Integer, k As Integer

    CurrentDb.Execute "CREATE TABLE DateRange (" _
                                    & " [Year] Integer," _
                                    & " [Quarter] Integer," _
                                    & " [Month] Integer)", dbFailOnError

    For i = 1989 To 2021
        For j = 1 To 4
            For k = 1 To 12
                CurrentDb.Execute "INSERT INTO DateRange ([Year], [Quarter], [Month])" _
                                    & " VALUES (" & i & ", " & j & ", " & k & ");"
            Next k
        Next j
    Next i

End Sub

然后在两个表 Presidents 和 DateRange 上运行 cross join 并进行日期过滤。使用这样的查询作为交叉表的来源:

年份

TRANSFORM Count(q.Year) AS CountOfYear
SELECT q.President
FROM 
  (SELECT p.ID, p.President, t.Year
   FROM Presidents AS p, 
       (SELECT sub.[Year]
        FROM DateRange sub
   GROUP BY sub.[Year])  AS t
   WHERE t.Year BETWEEN Year(p.StartDate) AND Year(p.EndDate))  AS q
GROUP BY q.ID, q.President
ORDER BY q.ID
PIVOT q.Year;

季度

TRANSFORM Count(q.Year) AS CountOfYear
SELECT q.President
FROM 
   (SELECT p.ID, p.President, t.Year, t.Quarter
    FROM Presidents AS p,
        (SELECT Year, Quarter 
         FROM DateRange sub
         GROUP BY Year, Quarter)  AS t
    WHERE t.Year BETWEEN Year(p.StartDate) AND Year(p.EndDate)
    AND DateSerial(t.Year, t.Quarter *3 - 2, 1) <= p.EndDate)  AS q
GROUP BY q.ID, q.President
ORDER BY q.ID
PIVOT (q.Year & ' Q' & q.Quarter);

月

这里的月份有点广泛,因为 Access 表/查询最多有 255 个。此外,当连接为数字字符串时,月份的顺序不是数字顺序,因为两位数会影响数字顺序:1 10 11 12 2 3 4。

要解决第一个问题,请使用 Year WHERE 过滤器运行两个交叉表。下面运行到 2009 年,其中特朗普不输出,然后从 2010 年到 2021 年运行相同的查询。为了解决第二个问题,使用交叉表的 IN() 子句预定义从 1989 年到 2009 年的所有 12 个月的许多列:

TRANSFORM Count(q.Year) AS CountOfYear
SELECT q.President
FROM 
     (SELECT p.ID, p.President, t.Year, t.Month
      FROM Presidents AS p,
           (SELECT Year, Month 
            FROM DateRange sub
            GROUP BY Year, Month)  AS t
      WHERE t.Year BETWEEN Year(p.StartDate) AND Year(p.EndDate)
      AND DateSerial(t.Year, t.Month, 1) <= p.EndDate)  AS q
WHERE q.Year <= 2009
GROUP BY q.ID, q.President
ORDER BY q.ID
PIVOT (q.Year & ' ' & q.Month) IN ("1989 1", "1989 2", "1989 3", "1989 4", "1989 5", 
                                   "1989 6", "1989 7", "1989 8", "1989 9", "1989 10",
                                   "1989 11", "1989 12", "1990 1", "1990 2",  "1990 3",
                                   "1990 4", "1990 5", "1990 6", "1990 7", "1990 8", 
                                   "1990 9", "1990 10", "1990 11", "1990 12",  
                                   ...
                                   "2008 1", "2008 2", "2008 3", "2008 4", "2008 5", 
                                   "2008 6", "2008 7", "2008 8", "2008 9", "2008 10", 
                                   "2008 11", "2008 12", "2009 1", "2009 2", "2009 3", 
                                   "2009 4", "2009 5", "2009 6", "2009 7", "2009 8", 
                                   "2009 9", "2009 10", "2009 11", "2009 12");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多