我想在ms-access中将行转换为列

时间:2016-11-14 16:43:07

标签: sql sql-server vba sqlite ms-access

我需要将行转换为MS Access数据库,VBA,SQL中的列,欢迎这些代码。

    | Name | Ticker | ID | Innovation | Quality | Year |
    | XYZ  |  PQR   | 11 | 1          | 1       | 2009 | 
    | XYZ  |  PQR   | 11 | 0          | 1       | 2010 | 
    | XYZ  |  PQR   | 11 | 1          | 0       | 2011 | 
    | XYZ  |  PQR   | 11 | 1          | 1       | 2012 | 

所需表

    | Year        | 2009 | 2010 | 2011 | 2012 |
    | Name        | XYZ  | XYZ  |  XYZ |  XYZ |
    | Ticker      | PQR  | PQR  | PQR  | PQR  |
    | ID          | 11   | 11   | 11   | 11   |
    | Innovation  | 1    | 0    | 1    | 1    |
    | Quality     | 1    | 1    | 0    | 1    |

从所需的表中可以看到,我正在尝试将Year行作为Column并列出除Year之外的所有列作为我的行。 我曾尝试在MS Access中使用Tranform和Pivot功能,但它只旋转一个变量。让我知道你的想法。

以下代码在转置所有变量时失败。

    TRANSFORM Max([Quality])
    SELECT Ticker
    FROM Table
    Where Ticker = "XYZ"
    GROUP BY Ticker
    PIVOT Year;

另外,如果可能,我想将其发布为PDF文档。

提前致谢, RVG

3 个答案:

答案 0 :(得分:1)

Access TRANSFORM不是非常直观且易于使用,我认为你不能这样使用它。每个结果行应该是您的表的聚合。我知道无法将以前的字段名称添加到新列中。

查看一个工作示例: TRANSFORM and PIVOT in Access 2013 SQL

您真正想要的只是对现有数据的新演示。

Excel可能有所帮助。

我从未从Access导出过pdf,但从Excel导出很容易。这是一个例子:

Sub ExportPdf(path As String, Optional openAfter As Boolean)

''calculate best range for print area
Dim lastCol As Integer
Dim firstRow As Integer
Dim lastRow As Integer

lastCol = pt.TableRange2.Columns(pt.TableRange2.Columns.Count).Column
firstRow = pt.TableRange2.Rows(1).Row
lastRow = ms.Cells(pt.TableRange2.Rows.Count * 3, 1).End(xlUp).Row

Worksheets(ContextSheet).PageSetup.PrintArea = Range(Cells(firstRow, 1), Cells(lastRow, lastCol)).Address

Worksheets(ContextSheet).ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
    path & "\Area " & getPivotTablePageFilters(getPivotTable()) & ".pdf", Quality:= _
    xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas:=False, _
    OpenAfterPublish:=openAfter
End Sub

答案 1 :(得分:1)

这是一个vb脚本,它从TableSource获取数据并将其转换为TableTranspose。必须使用名为FName的列设置第二个表以获取字段名称,并在源表中设置每年的列。

Function Transpose()
Set db = CurrentDb()
db.Execute ("delete * from TableTranspose")
Set RS = db.OpenRecordset("TableSource")
Set YrList = db.OpenRecordset("select distinct [Yr] from [TableSource] Group by [Yr]")

For Each F In RS.Fields
    FN = F.Name
    INS = "Insert Into TableTranspose (FName"
    SQL = "Select '" & FN & "'"
    YrList.MoveFirst
    Do While Not YrList.EOF
        YR = YrList.Fields("YR").Value
        INS = INS & ",[" & YR & "]"
        SQL = SQL & ",max(iif(YR=" & YR & ",[" & FN & "])) AS [" & YR & "]"
        YrList.MoveNext
        Loop
    SQL = SQL & " From TableSource"
    db.Execute (INS & ") " & SQL)

Next F
MsgBox ("Done")
End Function

这可以通过一次处理一个字段来匹配所需输出的布局,并循环遍历TableSource的每一年来查找构成TableTranspose中的行的数据。无论有多少字段或它们的名称都无关紧要。

它将在Year的输出中创建一行,这将是多余的 - 您可以将其删除,或者添加逻辑以在必要时跳过该字段。

对于样本中的4年数据,这似乎工作正常,并且应该延长到更多年。如果数据中存在太多年,您可能会限制SQL命令长度,但我认为不是。

如果要过滤TableSource中的记录,可以直接从底部附近的db.execute添加WHERE子句。

答案 2 :(得分:0)

数据总是与字段名称和年份相同吗?如果是这样,您可以使用UNION查询,例如:

Select "Name" as [FName],  max(iif(year="2009",name))as [2009], max(iif(year="2010"
,name)) as [2010], max(iif(year="2011",name)) as [2011], max(iif(year="2012", name)) as [2012] from Table group by FName

Union all Select "Ticker",  max(iif(year="2009",ticker)), max(iif(year="2010"
,ticker)), max(iif(year="2011",ticker)), max(iif(year=-"2012",ticker)) from Table group by FName

Union all Select "ID",  max(iif(year="2009",id)), max(iif(year="2010"
,id)), max(iif(year="2011",is)), max(iif(year="2012",id)) from Table group by FName

Union all Select "Innovation",  max(iif(year="2009",innovation)), max(iif(year="2010"
,innovation)), max(iif(year="2011",innovation)), max(iif(year=-"2012",innovation)) from Table group by FName

 Union all Select "Quality",  max(iif(year="2009",quality)), max(iif(year="2010"
,quality)), max(iif(year="2011",quality)), max(iif(year=-"2012",quality)) from Table group by FName