将数据库列转换为关联的行数据

Mat*_*cey 0 database ms-access

我继承了一个旧的访问数据库,其中包括一个表,该表的数据组织如下:

+-------+--------+-------------+-------------+-------------+----------------+
| Code  |  Year  |  Category1  |  Category2  |  Category3  |  ... etc ...   |
+-------+--------+-------------+-------------+-------------+----------------+
| A     |  2011  |          1  |          4  |         12  |                |
| A     |  2012  |          5  |          33 |         24  |                |
| B     |  2012  |          4  |          11 |         76  |                |
+-------+--------+-------------+-------------+-------------+----------------+
Run Code Online (Sandbox Code Playgroud)

我需要将此(实际表中有很多列)更改为以下结构:

+-------+--------+-------------+--------+
| Code  |  Year  |  Cat        |  Value |
+-------+--------+-------------+--------+
| A     |  2011  |  Category1  | 1      |
| A     |  2011  |  Category2  | 4      |
| A     |  2011  |  Category3  | 12     |
| A     |  2012  |  Category1  | 5      |
| A     |  2012  |  Category2  | 33     |
| A     |  2012  |  Category3  | 24     |
| B     |  2012  |  Category1  | 4      |
| B     |  2012  |  Category2  | 11     |
| B     |  2012  |  Category3  | 76     |
+-------+--------+-------------+--------+
Run Code Online (Sandbox Code Playgroud)

是否可以通过MS Access(我有2010版)中的某些自动转换来做到这一点?

Fio*_*ala 5

您可以使用联合查询:

SELECT a.* INTO NewTable FROM (
  SELECT [Code], [Year], "Category1" As Cat, Category1 As CatVal FROM MyTable
  UNION ALL
  SELECT [Code], [Year], "Category2" As Cat, Category2 As CatVal FROM MyTable
  UNION ALL
  <...> ) As a
Run Code Online (Sandbox Code Playgroud)

您可能想消除保留字词“ Year”,而无需使用它:http : //support.microsoft.com/kb/321266

如果类别很多,可以使用VBA使生活更轻松,例如:

Sub UnionSQL(ArrayColCommonWord As String, TableName As String)
Dim db As Database

Set db = CurrentDb

For Each fld In db.TableDefs(TableName).Fields
    If Left(fld.Name, Len(ArrayColCommonWord)) <> ArrayColCommonWord Then
        sSQL1 = sSQL1 & ",[" & fld.Name & "]"
    End If
Next

sSQL1 = "SELECT " & Mid(sSQL1, 2)

For Each fld In db.TableDefs(TableName).Fields
    If Left(fld.Name, Len(ArrayColCommonWord)) = ArrayColCommonWord Then
        sSQL = sSQL & vbCrLf & "UNION ALL" & vbCrLf
        sSQL = sSQL & sSQL1 & ",'" & fld.Name & "' As " & ArrayColCommonWord _
            & ",[" & fld.Name & "] As " & ArrayColCommonWord & "Val"
        sSQL = sSQL & vbCrLf & "FROM [" & TableName & "]"
    End If
Next

Debug.Print Mid(sSQL, 14)
''This will fail if there is an existing query
db.CreateQueryDef ArrayColCommonWord, Mid(sSQL, 14)

DoCmd.OpenQuery ArrayColCommonWord, acViewDesign

End Sub
Run Code Online (Sandbox Code Playgroud)