2013-04-05 74 views
2

我对此深感不足,因为我不使用数据库太多。我希望我已经尝试通过帮助其他网站上的InDesign和Photoshop用户付出代价就足够了!报告行和列的名称连接到一个值(Microsoft Access)

我可以使用Access或Excel进行下列操作。

我有数据,看起来像:

 
year President Vice 
1980 Reagan  Bush Sr. 
1984 Reagan  Bush Sr. 
1988 Bush Sr. Quayle 
1992 Clinton  Gore 
1996 Clinton  Gore 
2000 Bush Jr. Cheney 
2004 Bush Jr. Cheney 
2008 Obama  Biden 
2012 Obama  Biden 

我想要一份报告,看起来像:

 
Biden: Vice 2008, 2012 
Bush Jr.: President 2000, 2004 
Bush Sr.: President 1988; Vice 1980, 1984 
Cheney: Vice 2000, 2004 
Clinton: President 1992, 1996 
Gore: Vice 1992, 1996 
Obama: President 2008, 2012 
Quayle: Vice 1988 
Reagan: President 1980, 1984 

我无法搞清楚如何确定可以出现在任何一个共同的名字在表格上,以及如何获取报表的行和列标签。

这是真实数据的简化版本,与政治家无关。实际上有十个相关的列标签,而不仅仅是两个。 “老布什”举例说明一个人拥有两个不同的办公室。

目前没有任何情况下,同一行中的同一名称出现在两个不同的列中,但我不想排除这种可能性,除非它明显更复杂。

谢谢!

+0

您是否需要只做一次或需要自动重复运行? – PowerUser 2013-04-05 21:01:02

回答

2

我们需要做的第一件事是通过UNION查询将数据从“少数行,多列”转换为“少数列,多行”。 (我在一个叫[N_column_table表保存您的测试数据。)

SELECT [year], "President" AS office, [President] AS person 
FROM [N_column_table] 
UNION ALL 
SELECT [year], "Vice" AS office, [Vice] AS person 
FROM [N_column_table] 

如果该查询保存为“3_column_data”那么你可以使用它,就像在其他查询,报表等表格。(你将不得不当你建立你的真实数据查询添加〜8层UNION ALL结构。)

所以,现在我们的数据看起来像这样

year office  person 
1980 President Reagan 
1984 President Reagan 
1988 President Bush Sr. 
1992 President Clinton 
1996 President Clinton 
2000 President Bush Jr. 
2004 President Bush Jr. 
2008 President Obama 
2012 President Obama 
1980 Vice  Bush Sr. 
1984 Vice  Bush Sr. 
1988 Vice  Quayle 
1992 Vice  Gore 
1996 Vice  Gore 
2000 Vice  Cheney 
2004 Vice  Cheney 
2008 Vice  Biden 
2012 Vice  Biden 

现在,作为“粘在一起”的办公室,多年来,我们需要为此使用一点VBA功能。在Access中创建一个模块,并在下面的代码粘贴

Public Function ListTerms(person As String) As String 
Dim cdb As DAO.Database 
Dim rstOffice As DAO.Recordset, rstYear As DAO.Recordset 
Dim result As String, yearString As String 

Const YearSeparator = ", " 
Const OfficeSeparator = "; " 

Set cdb = CurrentDb 
result = "" 

Set rstOffice = cdb.OpenRecordset(_ 
     "SELECT DISTINCT office " & _ 
     "FROM 3_column_data " & _ 
     "WHERE person=""" & Replace(person, """", """""", 1, -1, vbBinaryCompare) & """ " & _ 
     "ORDER BY 1") 
Do While Not rstOffice.EOF 
    yearString = "" 
    Set rstYear = cdb.OpenRecordset(_ 
      "SELECT DISTINCT [year] " & _ 
      "FROM 3_column_data " & _ 
      "WHERE person=""" & Replace(person, """", """""", 1, -1, vbBinaryCompare) & """ " & _ 
       "AND office=""" & Replace(rstOffice!Office, """", """""", 1, -1, vbBinaryCompare) & """ " & _ 
      "ORDER BY 1") 
    Do While Not rstYear.EOF 
     If Len(yearString) > 0 Then 
      yearString = yearString & YearSeparator 
     End If 
     yearString = yearString & rstYear!Year 
     rstYear.MoveNext 
    Loop 
    rstYear.Close 
    Set rstYear = Nothing 
    If Len(result) > 0 Then 
     result = result & OfficeSeparator 
    End If 
    result = result & rstOffice!Office & " " & yearString 
    rstOffice.MoveNext 
Loop 
rstOffice.Close 
Set rstOffice = Nothing 
Set cdb = Nothing 
ListTerms = result 
End Function 

现在我们可以使用该功能在查询中列出的每个人,他们在办公室

SELECT personlist.[person], ListTerms(personlist.[Person]) as terms 
FROM (SELECT DISTINCT person FROM 3_column_data) personlist 

返回

person  terms 
Biden  Vice 2008, 2012 
Bush Jr. President 2000, 2004 
Bush Sr. President 1988; Vice 1980, 1984 
Cheney  Vice 2000, 2004 
Clinton  President 1992, 1996 
Gore  Vice 1992, 1996 
Obama  President 2008, 2012 
Quayle  Vice 1988 
Reagan  President 1980, 1984 
条款
+1

+1我在我的地方使用了'UNION ALL'。 'UNION'将只返回不同的行,但会给数据库引擎带来更大的负担。由于'UNION ALL'返回的行在这种情况下已经不同了,'UNION'没有任何好处。绝对而言,性能受到的影响可能不明显;但不值得打击。 – HansUp 2013-04-05 21:37:54

+0

@HansUp感谢您的提示!我会更新答案。 – 2013-04-05 21:41:15

+1

优秀!这个伎俩。我能够按照如何将它推广到更复杂的数据,甚至设法修改它以说明一些办事处在同一年由多个人持有的事实。但是如果没有你的模板,我就无处可去。谢谢! – user2250584 2013-04-05 23:12:51

相关问题