【问题标题】:POWERBI, DAX : concatenate strings, split, and keep substrings only oncePOWERBI, DAX : 连接字符串、拆分和只保留子字符串一次
【发布时间】:2020-11-18 13:30:25
【问题描述】:

我尝试执行以下操作:

  • 我有一列包含字符串,每列可以有几个子字符串,用分隔符“:”分隔
  • 我需要连接列字符串(我在这里做了一个过滤器,只保留有趣的行)
  • 然后根据分隔符“:”进行拆分
  • 如果子字符串重复,只保留一次。

例子:

ColumnHeader
AA:BB:CC
BB:DD
DD:AA:EE
EE:AA:DD:BB
BB:EE
...

预期结果将是一个唯一的字符串:

"AA:BB:CC:DD:EE"

您将如何在 DAX 中执行此操作以填充新列?

我希望像在 Python 中一样在 DAX 中找到 for/while 循环...但失败了。

我试过这个:

List =
VAR SIn = ""
VAR SOut = ""
VAR Cursor = 0
VAR SList =
        CONCATENATEX(
            FILTER(ATable, ATable[Name] = CTable[Name]),
            [ColumnHeader],
            ":")
VAR pos1 = FIND(":", SList, Cursor, len(SList))
VAR pos2 = FIND(":", SList, pos1, len(SList))
VAR elem = TRIM(MID(SList, pos1+1, pos2-pos1))

// following is not good but is what I would like to do:
VAR SOut = CONCATENATE(SOut, elem)
VAR SList = MID(SList, pos2, len(SList)-pos2)
VAR Cursor = pos2

// I need to loop ... but how ? ... as no for/while loops are possibles ?

感谢您的帮助。

======================================

感谢下面的答案,我设法解决了这个问题。

我仍然会提供更大的数据集,以便更好地了解全球问题:

我有 2 张桌子:

TABLE_BY_ELEMENT            
KEY GROUP   LIST        KEY_DATA
1   G1      AA:BB:FF    11
2   G1      CC:AA       22
3   G1      FF:DD:AA    33
4   G1      CC:DD:AA    44
5   G2      CC:FF:GG    55
6   G2      BB:AA       66
            
            
TABLE_BY_GROUP          
GROUP   GROUP_DATA      
G1      1111        
G2      2222        

我想这样查看数据:

RESULT_BY_GROUP     
GROUP   GROUP_DATA  NewList
G1      111         AA:BB:FF:CC:DD
G2      222         CC:FF:GG:BB:AA

还有:

RESULT_ELEMENT      
KEY LIST        KEY_DATA
1   AA:BB:FF    11
2   CC:AA       22
3   FF:DD:AA    33
4   CC:DD:AA    44
5   CC:FF:GG    55
6   BB:AA       66

我希望这样更容易理解。

【问题讨论】:

  • 最好在 Power Query/M 而不是 DAX 中执行此操作
  • 例如你有 10 行,你想要 1 行/列的最终输出?如果没有,请准确显示您的输入和输出,以及您想要的最终输出。
  • 我会尝试把它分成几行。使用查询编辑器每个值 1 行...最终结果是我想查看卡片(或表的 1 行)中的值,根据行 id 的切片器选择(数据示例中未显示)允许多选。

标签: string loops powerbi unique dax


【解决方案1】:

这不适合 DAX。如果您需要使用 DAX 使其成为动态度量,那么您可能需要重塑数据以使其更可用。例如,

ID   ColumnHeader
1    AA
1    BB
1    CC
2    BB
2    DD
3    DD
3    AA
3    EE
...

您可以在查询编辑器中使用拆分列 > 按分隔符工具进行拆分,并选择在冒号上拆分并展开成行。

一旦它采用这种更可用的格式,您就可以像这样在 DAX 中使用它:

List = CONCATENATEX( VALUES('Table'[ColumnHeader]), 'Table'[ColumnHeader], ":" )

借用 here 的逻辑,可能纯粹在 DAX 中这样做,但我不推荐这条路线。

List =
VAR LongString =
    CONCATENATEX ( VALUES ( 'Table1'[ColumnHeader] ), Table1[ColumnHeader], ":" )
VAR StringToPath =
    SUBSTITUTE ( LongString, ":", "|" )
VAR PathToTable =
    ADDCOLUMNS (
        GENERATESERIES ( 1, LEN ( StringToPath ) ),
        "Item", PATHITEM ( StringToPath, [Value] )
    )
VAR GroupItems =
    FILTER (
        SUMMARIZE ( PathToTable, [Item] ),
        NOT ISBLANK ( [Item] )
    )
RETURN
    CONCATENATEX ( GroupItems, [Item], ":" )

【讨论】:

  • 嗨,Alexi,谢谢,这似乎是一个有趣的解决方案。我正在对样本进行测试,并在查询编辑器中拆分数据。我现在看到两个问题: - 它会使我的表格大 4 倍:大约 4x15000 = 60000 行。可以吗? - 我将列表创建为新列,但我始终拥有整个列表的所有值。关键是:如果我只过滤奇数 Id,列表将不会更新。我怎样才能在我的可视化中实现这一点?谢谢
  • 60k 行完全没问题。您需要将 List 设为一个度量,而不是一个计算列,以便它是动态的。
  • 好的,太好了!!明天我会尝试用我的完整数据集来做这件事。只需检查最后两点: ... 1/ 我需要为此创建一个额外的表,因此在将数据拆分为列时不会破坏我的键的唯一性(示例中未显示键)。这是正确的吗 ? ... 2/我希望计算列考虑行上下文。您将如何更改代码以考虑“组”列,并且仅应使用同一组中的行进行连接?谢谢
  • 是的,您可能确实需要将其创建为一个新表,该表具有从原始表 ID 到新表 ID 的一对多关系。将此作为度量(不是计算列)将允许它基于过滤器上下文进行计算。它应该自动执行此操作,以响应您放置它的视觉对象创建的过滤器、切片器和上下文。
  • 您好,谢谢!你好,我是这样做的,效果很好。
【解决方案2】:

让你的表格如下所示-

现在在 Power Query 编辑器中尝试以下 Advance Editor 代码-

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcnS0cnKycnZWitWJVgKyXFzALBcXK6CMqyuY4+oK4gCFnJxgykAysQA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ColumnHeader = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"ColumnHeader", type text}}),
    
    
    //--NEW STEPS STARTS FROM HERE
    #"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 1, 1, Int64.Type),
    #"Reordered Columns" = Table.ReorderColumns(#"Added Index",{"Index", "ColumnHeader"}),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Reordered Columns", "ColumnHeader", Splitter.SplitTextByDelimiter(":", QuoteStyle.Csv), {"ColumnHeader.1", "ColumnHeader.2", "ColumnHeader.3", "ColumnHeader.4"}),
    #"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"ColumnHeader.1", type text}, {"ColumnHeader.2", type text}, {"ColumnHeader.3", type text}, {"ColumnHeader.4", type text}}),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type1", {"Index"}, "Attribute", "Value"),
    #"Removed Columns" = Table.RemoveColumns(#"Unpivoted Other Columns",{"Attribute", "Index"}),
    #"Removed Duplicates" = Table.Distinct(#"Removed Columns"),
    #"Sorted Rows" = Table.Sort(#"Removed Duplicates",{{"Value", Order.Ascending}}),
    #"Added Index1" = Table.AddIndexColumn(#"Sorted Rows", "Index", 1, 1, Int64.Type),
    #"Reordered Columns1" = Table.ReorderColumns(#"Added Index1",{"Index", "Value"}),
    #"Pivoted Column" = Table.Pivot(Table.TransformColumnTypes(#"Reordered Columns1", {{"Index", type text}}, "en-US"), List.Distinct(Table.TransformColumnTypes(#"Reordered Columns1", {{"Index", type text}}, "en-US")[Index]), "Index", "Value", List.Max),
    #"Merged Columns" = Table.CombineColumns(#"Pivoted Column",{"1", "2", "3", "4", "5"},Combiner.CombineTextByDelimiter(":", QuoteStyle.None),"Merged")
in
    #"Merged Columns"

这是最终的输出-

【讨论】:

  • 嗨,感谢这个例子。我注意到我有更复杂的现实生活数据。如果我有一个名为“GROUP”的额外列并且我希望对每个组进行一次连接,是否可以这样做。 GROUP1 将有第 1 行和第 2 行,而 GROUP2 第 3、4、5 行?结果就像一个两行表:GROUP1 AA:BB:CC:DD;和第 2 组 AA:BB:DD:EE。是否可以使用 Power Query 做到这一点?谢谢。
  • 我应该在这里添加更详细的示例数据吗?还是我应该发布一个新问题?
  • 可能...请提供更多示例数据以便理解。
  • 嗨,我添加了一组更大的数据和需要查找的结果。如果您仍然认为有可能,我对您使用 PowerQuery 的方式很感兴趣。谢谢
  • 嗨@Malo,请查看我的另一个答案以了解您的新案例。
【解决方案3】:

这是来自 Power Query Editor 的代码,考虑到 GROUP BY-

使用以下代码创建一个新表RESULT_BY_GROUP-

let
    Source = TABLE_BY_ELEMENT,
    #"Removed Columns" = Table.RemoveColumns(Source,{"KEY", "KEY_DATA"}),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Removed Columns", "LIST", Splitter.SplitTextByDelimiter(":", QuoteStyle.Csv), {"LIST.1", "LIST.2", "LIST.3"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"LIST.1", type text}, {"LIST.2", type text}, {"LIST.3", type text}}),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"GROUP"}, "Attribute", "Value"),
    #"Removed Columns1" = Table.RemoveColumns(#"Unpivoted Other Columns",{"Attribute"}),
    #"Removed Duplicates" = Table.Distinct(#"Removed Columns1"),
    #"Sorted Rows" = Table.Sort(#"Removed Duplicates",{{"GROUP", Order.Ascending}, {"Value", Order.Ascending}}),
    #"Grouped Rows" = Table.Group(#"Sorted Rows", {"GROUP"}, {{"all", each _, type table [GROUP=nullable text, Value=text]}}),
    #"Added Custom" = Table.AddColumn(#"Grouped Rows", "NewList", each [all][Value]),
    #"Extracted Values" = Table.TransformColumns(#"Added Custom", {"NewList", each Text.Combine(List.Transform(List.Sort(_), Text.From), ":"), type text}),
    #"Removed Columns2" = Table.RemoveColumns(#"Extracted Values",{"all"}),
    #"Merged Queries" = Table.NestedJoin(#"Removed Columns2", {"GROUP"}, TABLE_BY_GROUP, {"GROUP"}, "TABLE_BY_GROUP", JoinKind.LeftOuter),
    #"Expanded TABLE_BY_GROUP" = Table.ExpandTableColumn(#"Merged Queries", "TABLE_BY_GROUP", {"GROUP_DATA      "}, {"TABLE_BY_GROUP.GROUP_DATA      "}),
    #"Renamed Columns" = Table.RenameColumns(#"Expanded TABLE_BY_GROUP",{{"TABLE_BY_GROUP.GROUP_DATA      ", "GROUP_DATA"}}),
    #"Changed Type1" = Table.TransformColumnTypes(#"Renamed Columns",{{"GROUP", type text}, {"NewList", type text}, {"GROUP_DATA", Int64.Type}})
in
    #"Changed Type1"

这是最终的输出-

您可以使用基表 TABLE_BY_ELEMENT

轻松可视化您对表 RESULT_ELEMENT 的第二个要求

【讨论】:

  • 我无法复制粘贴下面的代码://--新步骤从这里开始因为我有错误。也许我的不同版本的 POwerBi ?您能否告诉我一步一步的过程,以便我可以在 Power Query 图形编辑器中重现它?
  • 你从哪里得到 //--新的步骤从这里开始?新代码不包含此行。如果您有确切名称的表 TABLE_BY_ELEMENT 和 TABLE_BY_GROUP 以及所有列名如示例所示,它只是代码的复制和粘贴应该可以工作。
猜你喜欢
  • 2017-03-13
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多