【问题标题】:Merging quasi-duplicate rows by moving values to new columns通过将值移动到新列来合并准重复行
【发布时间】:2025-12-25 17:15:07
【问题描述】:

我有一个包含数千行的表格,看起来有点像这样:

name sub_text sub_code other_data
a text1 code1 a_data
a text2 code2 a_data
a text3 code3 a_data
a text4 code4 a_data
b text1 code1 b_data
b text2 code2 b_data
c c_data

这些记录代表人,其中一些有 4 或 2 行,其中只有 sub_textsub_code 值不同。对于这 4 行或 2 行,有数十个 other_data 列(人的 ID、出生日期和地点等)是相同的。还有一些行没有任何重复,在这种情况下sub_textsub_code 值为空。

我想把这张表转换成这样的:

name sub_text1 sub_text2 sub_text3 sub_text4 sub_code1 sub_code2 sub_code3 sub_code4 other_data
a text1 text2 text3 text4 code1 code2 code3 code4 a_data
b text1 text2 code1 b_data
c c_data

我需要对记录进行排序,以便一个人只有一条记录,方法是将唯一不同的值添加到新列中,同时保留 other_data 字段和只有一条记录的人一条记录未受影响。

这最初是一个 Excel 表格,我还需要 Excel 中的“转换”表格。我不认为 Excel 可以做这样的事情,所以我创建了一个数据库(我现在只在 Access 中拥有它)希望我可以用 SQL 做更多的事情。我不知道如何解决这个问题。有什么想法吗?

【问题讨论】:

  • 在 Windows Excel 2010+ 或 Office 365 中,您可以使用 Power Query 轻松完成此操作。在其他版本中,VBA 解决方案可能是最简单的。
  • 数据未针对关系数据库模式进行规范化。将数据重新排列为具有相同类型数据的多个相似名称字段也不是规范化结构。这个数据实际上应该是两个表。

标签: sql excel ms-access


【解决方案1】:

基本上,您需要枚举行,然后使用条件聚合。这在大多数数据库中都很容易——使用row_number()——但在 MS Access 中却很痛苦。这是一种方法,假设列中的值没有重复:

select num, other_data,
       sum(iif(seqnum = 1, sub_text, null)) as sub_text_1,
       sum(iif(seqnum = 2, sub_text, null)) as sub_text_2,
       sum(iif(seqnum = 3, sub_text, null)) as sub_text_3,
       sum(iif(seqnum = 4, sub_text, null)) as sub_text_4,
       sum(iif(seqnum = 1, sub_code, null)) as sub_code_1,
       sum(iif(seqnum = 2, sub_code, null)) as sub_code_2,
       sum(iif(seqnum = 3, sub_code, null)) as sub_code_3,
       sum(iif(seqnum = 4, sub_code, null)) as sub_code_4
from (select t.*,
             (select count(*)
              from t as t2
              where t2.name = t.name and t2.sub_text <= t.sub_text
             ) as seqnum
      from t
group by name, other_data;

【讨论】:

    【解决方案2】:

    在 Windows Excel 2010+ 和 Office 365 中可用的 Power Query 中,您可以通过以下方式轻松完成此操作

    • 按重复列分组(在您的示例中为nameother_data
    • 然后将合并的子表代码和文本列提取到分隔列表中
    • 将该列表拆分为新列

    使用 Power Query

    • 选择数据表中的某个单元格
    • Data =&gt; Get&amp;Transform =&gt; from Table/Range
    • 当 PQ 编辑器打开时:Home =&gt; Advanced Editor
    • 记下第 2 行中的表 Name
    • 粘贴下面的 M 代码代替您看到的内容
    • 将第 2 行中的表名称更改回最初生成的名称。
    • 阅读 cmets 并探索 Applied Steps 以了解算法

    M 码

    let
        Source = Excel.CurrentWorkbook(){[Name="Table10"]}[Content],
    
    //Group by Name and Other Data
    //  extract a delimited list of the sub_text and sub_codes
        #"Grouped Rows" = Table.Group(Source, {"name", "other_data"}, {
            {"sub_text", each Text.Combine([sub_text],";"), type text},
            {"sub_code", each Text.Combine([sub_code],";"), type text}    
            }),
    
    //split the delimited lists into separate columns.
        #"Split Column by Delimiter" = Table.SplitColumn(#"Grouped Rows", "sub_text", 
                    Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv)),
        #"Split Column by Delimiter1" = Table.SplitColumn(#"Split Column by Delimiter", "sub_code", 
                    Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv))
    in
        #"Split Column by Delimiter1"
    

    【讨论】:

    • 谢谢!我不熟悉这种语法,所以我试图了解它如何处理我的实际数据。如果我有第三组名为sub_lang 的列必须以相同的方式移动怎么办? this 会怎样? (抱歉,无法在评论中粘贴那么多字符。)
    • @Emcs 您可以手动将适当的代码行添加到#"Grouped Rows" 函数(类似于您所看到的),并添加额外的Split Column 行该子组。