Microsoft Access - 将具有相同密钥的内容合并到新表中

时间:2013-01-31 11:23:29

标签: ms-access ms-office

在Microsoft Access中,我想将具有相同键(=重复项)的表中的特定列合并到新表中。

源表看起来像这样

Key Content
Apple   X
Banana  B
Banana  D
Banana  E
Banana  G
Lemon   A
Lemon   X
Orange  A

我想创建一个新表,其中每个键只有一个条目,每个键的字段由累积到一个字段中的所有相应“内容”字段组成。每个“内容”值应该用某些东西分隔,例如:

Apple   X
Banana  B<x>D<x>E<x>G
Lemon   A<x>X
Orange  A

我希望如上所述,但如果它们位于不同的字段/列中,它也可以使用,如下所示:

Apple   X
Banana  B   D   E   G
Lemon   A   X
Orange  A

我真的很感谢这方面的帮助。当谷歌搜索时,我发现退出了一些第三方附加组件(如此http://www.tucows.com/preview/1586663/MS-Access-Join-Two-Tables-Software)似乎正在解决这个问题,但肯定可以通过MS Access本身来完成...。或...?< / p>

2 个答案:

答案 0 :(得分:1)

一个版本是使用UDF和此查询:

SELECT Distinct Fruit.Key, 
    ConcatADO("SELECT Content FROM Fruit WHERE Key='" & [Key] & "'","<x>","<x>") 
       AS AllRows 
INTO NewFruit
FROM Fruit

用户定义函数(UDF)

Function ConcatADO(strSQL As String, strColDelim, strRowDelim)
   Dim rs As New ADODB.Recordset
   Dim strList As String

   On Error GoTo Proc_Err

       If strSQL <> "" Then
           rs.Open strSQL, CurrentProject.Connection
           strList = rs.GetString(, , strColDelim, strRowDelim)
           strList = Mid(strList, 1, Len(strList) - Len(strRowDelim))
       End If

       ConcatADO = strList

   Exit Function

Proc_Err:
       ConcatADO = "***" & UCase(Err.Description)
End Function

在查询设计窗口中工作,您可以创建交叉表

TRANSFORM Min(Fruit.Content) AS MinOfContent
SELECT Fruit.Key
FROM Fruit
GROUP BY Fruit.Key
PIVOT Fruit.Content;

哪会返回

Key     A   B   D   E   G   X
Apple                       X
Banana      B   D   E   G   
Lemon   A                   X
Orange  A

然后,您可以保存交叉表并基于交叉表创建新查询。此查询可以是Make Table查询以获取新表,但正如您所看到的,您有多个列。

如果每个键都有预定数量的可能行​​,则还有其他方法。

最后,你必须问问自己,de-normalizing真的可以走了吗?

答案 1 :(得分:1)

另一种方法是使用两列(Key,Content)创建表,然后运行下面的函数将数据复制到新表中。您必须用表名替换“ExistingTableName”和“NewTableName”。

Sub CreateNewTable()
    Dim rs As Recordset
    Dim rsContent As Recordset
    Dim strContent As String
    'Select and loop through all keys
    Set rs = CurrentDb.OpenRecordset("SELECT DISTINCT Key FROM [ExistingTableName]")
    Do Until rs.EOF
      'Select all content records for this key and combine into a string
      Set rsContent = CurrentDb.OpenRecordset("SELECT Content FROM [ExistingTableName] WHERE Key = " & Chr(34) & Nz(rs!Key) & Chr(34))
      strContent = ""
      Do Until rsContent.EOF
        strContent = strContent & rsContent!Content & ","
        rsContent.MoveNext
      Loop
      If Len(strContent) > 0 Then
      strContent = Mid(strContent, 1, Len(strContent) - 1)
      End If
      CurrentDb.Execute "INSERT INTO [NewTableName] (Key, Content) VALUES (" & Chr(34) & Nz(rs!Key) & Chr(34) & ", " & Chr(34) & Nz(strContent) & Chr(34) & ")"
      rs.MoveNext
    Loop

    Set rs = Nothing
    Set rsContent = Nothing
End Sub

如果没有VBA,我认为没有办法做到这一点。

当您使用关系数据库时,您应该考虑使用一个表来存储密钥,使用另一个表来存储内容(每行/每个记录一个内容),然后通过使用第三个表或添加'来链接它们。 key'作为内容表中的外键。我也总是使用自动编号作为所有MS Access表中的主键,如果不是出于其他原因这是个好主意,只是为了避免损坏并使你能够将'aple'等拼写错误更改为'apple'而不用打破你的关系。