当原始数据包含日期范围时,MS Access交叉表查询

时间:2016-11-23 16:18:12

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

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

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
…

请告诉我这是否有意义,或者我是否应该进一步阐述。

2 个答案:

答案 0 :(得分:0)

您正在寻找的字段如下所示:

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

答案 1 :(得分:0)

考虑填充一个单独的 DateRange 表,其中包含所有范围值,包括有序的 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;

Year Crosstab Output

<强>季

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);

Quarter Crosstab Output

<强>月

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

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

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");

Month Crosstab First Output Month Crosstab Second Output