PowerBI 将每个 ID 的多行数据转换为列

PowerBI pivot multiple rows for each ID into columns

在 Power BI 中,我有如下所示的数据:

ID DateTime Name
gfdh-65gfhd-654h 2021-12-01 21:00:00 am George
gfdh-65gfhd-654h 2021-12-02 21:00:00 am Paul
gfdh-65gfhd-654h 2021-12-03 21:00:00 am Tom
nbvc-65khgf-764g 2021-12-02 21:00:00 am George
nbvc-65khgf-764g 2021-12-03 21:00:00 am Tom

每个 ID 的行数是可变的,我希望它看起来像这样:

ID DateTime Name DateTime1 Name1 DateTime2 Name2
gfdh-65gfhd-654h 2021-12-01 21:00:00 am George 2021-12-02 21:00:00 am Paul 2021-12-03 21:00:00 am Tom
nbvc-65khgf-764g 2021-12-02 21:00:00 am George 2021-12-03 21:00:00 am Tom

其中每个 ID 的列数与原始 table 中每个 ID 的行数相关。

这可以在 Power M 中完成吗?如果可以,怎么做?

你能试试这个吗

let
  Source = Table.FromRows(
    Json.Document(
      Binary.Decompress(
        Binary.FromText(
          "i45WSk9LydA1M01Py0gBUiYZSjpKRgZGhrqGRroGhgpGhlYGBkCkEOALlHBPzS9KT1WK1cGvzQhNW0BiaQ5BTcZomkLyc8F68pLKkoGKszPS03TNzUzS8VmE5D582rBaFQsA",
          BinaryEncoding.Base64
        ),
        Compression.Deflate
      )
    ),
    let
      _t = ((type nullable text) meta [Serialized.Text = true])
    in
      type table [ID = _t, DateTime = _t, Name = _t]
  ),
  #"Changed Type" = Table.TransformColumnTypes(
    Source,
    {{"ID", type text}, {"DateTime", type datetime}, {"Name", type text}}
  ),
  #"Changed Type1" = Table.TransformColumnTypes(#"Changed Type", {{"DateTime", type text}}),
  #"Grouped Rows" = Table.Group(
    #"Changed Type1",
    {"ID"},
    {
      {
        "ad",
        each _,
        type table [ID = nullable text, DateTime = nullable text, Name = nullable text]
      }
    }
  ),
  #"Added Custom" = Table.AddColumn(
    #"Grouped Rows",
    "DateTime",
    each
      let
        x = [ad],
        y = x[DateTime],
        z = Text.Combine(y, ",")
      in
        z
  ),
  #"Added Custom1" = Table.AddColumn(
    #"Added Custom",
    "Name",
    each
      let
        x = [ad],
        y = x[Name],
        z = Text.Combine(y, ",")
      in
        z
  ),
  #"Removed Columns" = Table.RemoveColumns(#"Added Custom1", {"ad"}),
  #"Split Column by Delimiter" = Table.SplitColumn(
    #"Removed Columns",
    "DateTime",
    Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv),
    {"DateTime.1", "DateTime.2", "DateTime.3"}
  ),
  #"Changed Type2" = Table.TransformColumnTypes(
    #"Split Column by Delimiter",
    {{"DateTime.1", type datetime}, {"DateTime.2", type datetime}, {"DateTime.3", type datetime}}
  ),
  #"Split Column by Delimiter1" = Table.SplitColumn(
    #"Changed Type2",
    "Name",
    Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv),
    {"Name.1", "Name.2", "Name.3"}
  ),
  #"Changed Type3" = Table.TransformColumnTypes(
    #"Split Column by Delimiter1",
    {{"Name.1", type text}, {"Name.2", type text}, {"Name.3", type text}}
  ),
  #"Reordered Columns" = Table.ReorderColumns(
    #"Changed Type3",
    {"ID", "DateTime.1", "Name.1", "DateTime.2", "Name.2", "DateTime.3", "Name.3"}
  )
in
  #"Reordered Columns"

上面的结果如下

这是一种方法 - 为每个 ID 创建一个分区,然后排序,取消透视日期/名称,然后重新加入并重新排序。

这将针对每个 ID 可变的、未指定数量的条目进行缩放,并将适当地转换和重新排序。

let
    fnPartition = (MyPartition as table) =>
    let
        #"fnP Sorted Rows" = Table.Sort(MyPartition,{{"DateTime", Order.Ascending}}),
        #"fnP Added Index" = Table.AddIndexColumn(#"fnP Sorted Rows", "Index", 0, 1, Int64.Type),
        #"fnP Combined Data" = Table.Combine({fnUnpivot(#"fnP Added Index", "DateTime", 0), fnUnpivot(#"fnP Added Index", "Name", 1)}),
        #"fnP Transposed Back" = Table.Transpose(#"fnP Combined Data"),
        #"fnP Promoted Headers" = Table.PromoteHeaders(#"fnP Transposed Back", [PromoteAllScalars=true])
    in
        #"fnP Promoted Headers",

    fnUnpivot = (MyTable as table, MyHeader as text, MySkipRows as number) =>
    let
        #"fnU Added Header" = Table.AddColumn(MyTable, "Header", each MyHeader & Text.From([Index]), type text),
        #"fnU Selected Columns" = Table.SelectColumns(#"fnU Added Header",{"ID", MyHeader, "Header"}),
        #"fnU Pivoted" = Table.Pivot(#"fnU Selected Columns", List.Distinct(#"fnU Selected Columns"[Header]), "Header", MyHeader),
        #"fnU Demoted Headers" = Table.DemoteHeaders(#"fnU Pivoted"),
        #"fnU Transposed" = Table.Transpose(#"fnU Demoted Headers"),
        #"fnU Removed Top Rows" = Table.Skip(#"fnU Transposed",MySkipRows)
    in
        #"fnU Removed Top Rows",

    fnSortTransform = (value) => Text.End(value, 1) & Text.Start(value, 1),

    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WSk9LydA1M01Py0gBUiYZSjpKRgZGhrqGRroGhgpGhlYGBkAEFHVPzS9KT1WK1cGvxwhZT0BiaQ5BHcbIOkLyc8Ea8pLKkoEqszPS03TNzUzScVqB5Cx8erBags9VJsga/HNyKpViYwE=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID = _t, DateTime = _t, Name = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"DateTime", type datetime}}),
    #"Created Partitions" = Table.Group(#"Changed Type", {"ID"}, {{"Data", each fnPartition(_), type table}}),
    #"Combined Partitions" = Table.Combine(#"Created Partitions"[Data]),
    #"Reordered Columns" = Table.ReorderColumns(#"Combined Partitions",List.Combine({List.FirstN(Table.ColumnNames(#"Combined Partitions"),1), List.Sort(List.Skip(Table.ColumnNames(#"Combined Partitions"),1), (a, b) => Value.Compare(fnSortTransform(a), fnSortTransform(b)))})),
    #"Changed Type Text" = Table.TransformColumnTypes(#"Reordered Columns", List.Transform(List.Select(Table.ColumnNames(#"Reordered Columns"),each not Text.Contains(_,"Date")), each {_, type text})),
    #"Changed Type DateTime" = Table.TransformColumnTypes(#"Changed Type Text", List.Transform(List.Select(Table.ColumnNames(#"Reordered Columns"),each Text.Contains(_,"Date")), each {_, type datetime}))
in
    #"Changed Type DateTime"

这个returns: