如何将两个Table.AddColumn代码合并为单个Power Query步骤?
合并Power Query中两个Table.AddColumn步骤的实现方案
需求说明
现有Power Query代码通过两个独立的Table.AddColumn()步骤分别完成以下数据匹配逻辑:
- OUT1生成逻辑:从Source表的STR列提取固定位置的数字片段并拼接(如从
abc.sec712.fir001.wpqdata中提取712和001拼接为712001),匹配Codes表的VAL2列,返回对应的CODE值,无匹配则返回"NOT FOUND"。 - OUT2生成逻辑:针对Source表的NUM列值,在Codes表的VAL1列中筛选前缀匹配的记录,优先选择与NUM长度差异最小的项(长度相同时保留原表中最先出现的记录);NUM为空时返回null,无匹配则返回"NOT FOUND"。
需要将这两个逻辑合并到单个Table.AddColumn()步骤中,简化代码结构,同时保证输出结果与原代码一致。
解决方案
可以通过在单个Table.AddColumn()的行上下文函数中同时计算OUT1和OUT2的结果,将两者封装为记录类型的列,再通过Table.ExpandRecordColumn()将记录拆分为两个独立的文本列。修改后的完整代码如下:
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("ZY3LCsIwEEX/JesSMsl0kiwFobZqK4WsQhexVXDnC/x9UyVqEAbu5XCY6z1bbGtWMCBCjMmGwrO+72JVwmqjbIKNa2cokQx8YLVysSJaW2qT4LrbxErKAonEdq+X8cJ+5LfDqEHy4+kqBPDH+TKFe/hZ/mqqpFkDEJlWt1Wu4VvDXFs2LtOk+B8dng==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [TRS = _t, NUM = _t, STR = _t]), Codes = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("XZDNjoMwDITfhXMPdn4cfOymqEUNzQqCWhX1/V9jbbPsYU8gT+absbetq6W0oXanLjKmJN/kCcB3n9PWLfM8LYvMOLmY0MlfcBEgmTrnXK+zzDwQq9OBA0DTxvM5P0eZoaPgfNRXFPsABzc/lYtEIbByfQw97eo85jkrNwJ5APVK9kFelGzemCAhqRelABydct07/a80lHKvg0ouUI8sDtVJXphepykXPQT2jplRXyYAcKbmda0t25k8s3UKIu7WYV0vqOjgKREIQNH0F/0ehq/81jtyiFFzzbuTH7LP/WG5xERgxyDE34Vaa5MtFJHJsD0Amba+Xt9tNU321MJOC++Zt1Ku7SYz8oxkVaU8Rov9/AA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [CODE = _t, VAL1 = _t, VAL2 = _t]), CustomCombined = Table.AddColumn( Source, "CombinedResults", (row) => let // 计算OUT1的逻辑 strNumPart = Text.Middle(row[STR],7,3) & Text.Middle(row[STR],14,3), out1 = try Table.SelectRows(Codes, each [VAL2] = strNumPart)[CODE]{0} otherwise "NOT FOUND", // 计算OUT2的逻辑 out2 = if row[NUM] = "" then null else let filteredCodes = Table.SelectRows(Codes, (x) => let sortedVals = List.Sort({x[VAL1], row[NUM]}, each Text.Length(_)) in Text.StartsWith(sortedVals{1}, sortedVals{0}) ), indexedCodes = Table.AddIndexColumn(filteredCodes, "Index"), hasMatches = Table.RowCount(indexedCodes) > 0 in if hasMatches then Table.First(Table.Sort(indexedCodes, (y) => Number.BitwiseShiftLeft(Number.Abs(Text.Length(row[NUM]) - Text.Length(y[VAL1])), 32) + y[Index] ))[CODE] else "NOT FOUND" in [OUT1 = out1, OUT2 = out2], type [OUT1 = text, OUT2 = text] ), // 展开记录列为独立的OUT1和OUT2列 ExpandedResults = Table.ExpandRecordColumn(CustomCombined, "CombinedResults", {"OUT1", "OUT2"}, {"OUT1", "OUT2"}) in ExpandedResults
关键说明
- 合并逻辑封装:在
Table.AddColumn()的行上下文函数中,先分别计算OUT1和OUT2的结果,再将两者打包为记录类型返回,同时指定记录的类型约束以提升性能。 - 结果展开:通过
Table.ExpandRecordColumn()将记录列拆分为两个独立的文本列,与原代码的输出结构完全一致。 - 逻辑一致性:保留了原代码中所有匹配规则(包括TRY-CATCH处理、前缀匹配逻辑、排序优先级),确保输出结果与原代码完全相同。
内容的提问来源于stack exchange,提问作者Rasec Malkic
相关产品推荐
相关产品推荐

