Excel: 如何转置 select 列并按重复值分组? (一维到二维 table)

Excel: How to transpose select columns and group by repeated values? (1D to 2D table)

我正在处理交易的数据转储,它不是出于任何目的以非常友好的格式从特定系统导出的。

Excel 中的数据目前由大约 700,000 行组成,而一旦组织正确,应该只包含大约 70,000 行,其中一个特定列的唯一值被转置到一些其他列中。

目前我正在使用下面这样的(简化的)示例;

Request_ID   Status       Field_Name       Value
01000        Rejected     Name             John Smith
01000        Rejected     Acc Number       123456
01000        Rejected     Date             1/12/2015
01000        Rejected     Enquiry Type     Type 1
01000        Rejected     Reason           Reason 1
01001        Completed    Name             Jane Jones
01001        Completed    Acc Number       123457
01001        Completed    Date             1/12/2015
01001        Completed    Enquiry Type     Type 2
01001        Completed    Reason           Reason 2

前两列(Request_IDStatus)只是重复值以满足大量数据行与每个单独的请求有关。

Field_Name 列是特定列在每个唯一的行上重复相同的一组值 Request_ID - Value 列列出了与每个 Field_Name.

相关的相应值

我想将第 3 列和第 4 列(Field_NameValue)转置为行以生成类似下面的内容:

Request_ID  Status     Name          Acc Number    Date       Enquiry Type    Reason
01000       Rejected   John Smith    123456        1/12/2012  Type 1          Reason 1
01001       Completed  Jane Jones    123457        1/12/2012  Type 2          Reason 2

如您所见,上面的第二个示例更符合逻辑并且冗余数据更少 - 此外还允许进行简单的过滤和分析。

因此,我的第一个调用点是尝试通过将数据插入数据透视表来实现上述操作,但是我似乎无法理解其中的逻辑。或者,如果我能够将字段放入类似的列位置,那么这些值将简单地计算 table 正文中的计数,而不是值本身(数据透视表的性质)。

是否可以使用Transpose功能? (如果是这样,我很乐意自己调查)

有没有我没有考虑过的替代解决方案?

(旁注 - 我的数据转储中还有其他列,我没有包含在示例中,因为它们包含的值对与个人相关的每一行简单重复Request_ID - 所以我想我可以对上面适用的任何解决方案使用相同的逻辑)

如果您能指出正确的方向或提供任何指导,我将不胜感激,因为我很困惑。

假设您的数据在 A:D 列中。将列 Request_ID 复制到 Col G。使用 excel Remove Duplicates 函数获取唯一的请求 ID。从 Col H 开始为所有可能的字段名称(如名称、帐户编号等)制作 headers,并使用以下公式。

H2 =VLOOKUP(G2,$A:$D,2,FALSE)

I2 =INDIRECT(ADDRESS(SUMPRODUCT(--($A:$A=$G2)*--($C:$C=I)*ROW($A:$A)),4))

为所有其他字段名称拖动 I2 公式。

这是一个Google Sheet

我已经尝试使用您发布的数据并且工作正常。如果您想将整个过程自动化,您可以尝试为所有这些步骤录制宏。

选择任何单元格,说 G6 并输入:

=INDEX(A:A,(ROWS(:1)-1)*5+2)

然后抄下来。在H6中输入:

=INDEX(B:B,(ROWS(:1)-1)*5+2)

然后抄下来。最后在I6中输入:

=OFFSET($D,COLUMNS($A:A)-1+(ROWS(:1)-1)*5,0)

并上下复制此单元格:

SQL中条件聚合查询的经典需求。您的初始示例反映了 Entity-Attribute-Value 模型。要正确对齐不同的列,在 Field_Name 列上有条件地聚合,returning Value[=54 的最大值(唯一值) =],按重复列分组(添加到所有其他重复列的 SELECTGROUP BY):

条件聚合查询

SELECT Request_ID, Status, 
       MAX(IIF(Field_Name='Name', Value, NULL)) AS Name,
       MAX(IIF(Field_Name='Acc Number', Value, NULL)) AS [Acc Number],
       MAX(IIF(Field_Name='Date', Value, NULL)) AS [Date],
       MAX(IIF(Field_Name='Enquiry Type', Value, NULL)) AS [Enquiry Type]
       MAX(IIF(Field_Name='Reason', Value, NULL)) AS [Reason]
FROM [Worksheet$]
GROUP BY Request_ID, Status

如果在 PC 上使用 Excel,您可以使用 ACE SQL 引擎(Windows .dll 文件)运行 SQL 查询VBA 中的工作簿。如果使用 Mac,将数据导入数据库,如 SQLite 和 运行 上面的查询(将 IIF() 替换为 CASE 语句)。对于超过 700,000 条记录,与内联公式或嵌套 for 循环和数组相比,SQL 可能是一个可靠的解决方案。

下面是使用 ADO 的 Windows 解决方案(两个可用连接),其中数据驻留在 DATA 选项卡中,其中包含空白 RESULTS 用于查询结果的选项卡。

Sub RunSQL()
    Dim conn As Object, rst As Object
    Dim strConnection As String, strSQL As String, i As Integer

    Set conn = CreateObject("ADODB.Connection")
    Set rst = CreateObject("ADODB.Recordset")

    ' CONNECTION STRINGS (DRIVER AND PROVIDER)
'    strConnection = "DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _
'                      & ActiveWorkbook.FullName ";"
    strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;" _
                       & "Data Source='" & ActiveWorkbook.FullName & "';" _
                       & "Extended Properties=""Excel 8.0;HDR=YES;"";"

    strSQL = " SELECT Request_ID, Status," _
               & "    MAX(IIF(Field_Name='Name', Value, NULL)) AS Name," _
               & "    MAX(IIF(Field_Name='Acc Number', Value, NULL)) AS [Acc Number]," _
               & "    MAX(IIF(Field_Name='Date', Value, NULL)) AS [Date]," _
               & "    MAX(IIF(Field_Name='Enquiry Type', Value, NULL)) AS [Enquiry Type]," _
               & "    MAX(IIF(Field_Name='Reason', Value, NULL)) AS [Reason]" _
               & " FROM [DATA$]" _
               & " GROUP BY Request_ID, Status;"            
    ' OPEN CONNECTION AND RECORDSET
    conn.Open strConnection
    rst.Open strSQL, conn

    ' HEADERS
    For i = 0 To rst.Fields.Count - 1
        Worksheets("RESULTS").Cells(1, i + 1) = rst.Fields(i).Name
    Next i           
    ' DATA ROWS
    Worksheets("RESULTS").Range("A2").CopyFromRecordset rst

    rst.Close: conn.Close
End Sub

或者,对于可变数量的 Field_Name,您可以使用 ACE SQL 的唯一 crosstab query,它避免了硬编码值的可能性,例如上述聚合中的条件。并且因为 ACE SQL 将列限制为 255,下面的查询只能 return 253 个或更少 Field_Name 的不同值(对于重复的 groupby 列为 2):

交叉表查询

strSQL = " TRANSFORM Max(Value)" _
           & " SELECT Request_ID, Status" _
           & " FROM [DATA$]" _
           & " GROUP BY Request_ID, Status" _
           & " PIVOT Field_Name;"

数据

结果

根据您的 Excel 版本,您可以使用 Power Pivot (2010/2013) 或 Get & Transform (2016) 适当地转换数据。您的数据(如果尚未在 table 中)将转换为一个。

对于后者,Selecting From Table 打开查询编辑器。在 select 字段名称和值列之后,select TransformPivot Column

这将打开一个“数据透视列”对话框。您要确保 select 离子如下所示。此外,您必须 select advanced 才能进入 do not aggregate 选项。

Select 好的,你得到了你问题中的结果。当您保存查询时,它会将结果写入新的工作表。您需要正确设置日期列的格式。

我不确定这将如何处理 700,000 行。您可能需要 64 位 Excel.

但是,查看对其他回复的一些评论,此解决方案应该适用于不同数量的 Field Name / Value 对。