Forum Discussion

bernate's avatar
bernate
Helper III
1 year ago
Solved

Custom Column Based on Groups in 2 Other Columns

Hello, 

 

I am trying to create a custom column that would designate which employees are still "in training." My data looks like below:

 

Employee NameTrainingTrainingStatus DateTimeTraining StatusDesired Result
ALeadership6/24/2025 11:00StartedTraining Complete
ALeadership6/24/2025 11:00In ProgressTraining Complete
ALeadership6/24/2025 11:10CompleteTraining Complete
ACommunication6/24/2025 11:15StartedIn Training
ACommunication6/24/2025 11:15In ProgressIn Training
BCommunication6/24/2025 11:12StartedTraining Complete
BCommunication6/24/2025 11:00In ProgressTraining Complete
BCommunication6/24/2025 11:28CompleteTraining Complete
BLeadership6/24/2025 11:30StartedTraining Complete
BLeadership6/24/2025 11:30In ProgressTraining Complete
BLeadership6/24/2025 11:36CompleteTraining Complete
CLeadership6/24/2025 11:15StartedIn Training
CLeadership6/24/2025 11:15In ProgressIn Training
CCommunication6/24/2025 11:25StartedIn Training
CCommunication6/24/2025 11:25In ProgressIn Training

 

An employee can work on and complete multiple trainings and a training can have multiple employees at the same time. From this list, I want to know how many employees are still "In Training"- if the last timestamp of the training has status = "Started" or "In Progress" then "In Training" else if last timestamp of the training has status = "Complete" then "Training Complete."

 

If this can be done more easily in DAX then I am open to that as well. I have just been trying this in Power Query by grouping but I am stuck on how to loop through all of the employees and all of the trainings to get the result. Thanks!

  • let
        status = [Complete = "Training Complete"],
        Source = your_data,
        group = Table.Group(
            Source, 
            {"Employee Name", "Training"}, 
            {
                {"rows", each _}, 
                {"status", (x) => Record.FieldOrDefault(status, Table.Max(x, "TrainingStatus DateTime")[Training Status], "In Training")}
            }
        ),
        result = Table.ExpandTableColumn(group, "rows", {"TrainingStatus DateTime", "Training Status"})
    in
        result

13 Replies

  • Here is a pbix file that contains one possible solution.
    It uses Table.Group and Table.TransformColumns to work on nested tables in order to get the desired result.

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("nZIxC8IwEIX/SshcaBJtETebSXAQdCsdgg01YNOSxP9vHBSqcHe6Jcfdx713r235jhf8YE1vQ7y6OX/qUq1LJVTFpNwKkSunZEKyfX6dg3He+YHpaZxvNlneFSTE3rNjmIZgY/wTI5+Ydz/EyIXx7t3FJDf5L0y1EJT3eoF+mF+q+WQ0KEMRTEUpZF9RktpQrG3A86woQSEgqIIATE1Ro+GwwSkhDMMR0ehJ8AXweWCH7gE=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Employee Name" = _t, Training = _t, #"TrainingStatus DateTime" = _t, #"Training Status" = _t, #"Desired Result" = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"Employee Name", type text}, {"Training", type text}, {"TrainingStatus DateTime", type datetime}, {"Training Status", type text}, {"Desired Result", type text}}),
        #"Grouped Rows" = Table.Group(#"Changed Type", {"Employee Name", "Training"}, {{"AllRows", each _, type table [Employee Name=nullable text, Training=nullable text, TrainingStatus DateTime=nullable datetime, Training Status=nullable text, Desired Result=nullable text]}}),
        Custom1 = Table.TransformColumns(#"Grouped Rows", {{"AllRows", each Table.AddColumn(_, "Result",  (r)=> if r[#"TrainingStatus DateTime"] = List.Max([#"TrainingStatus DateTime"]) then r[#"Training Status"] else null, type text), type table}}),
        Custom2 = Table.TransformColumns(Custom1, {{"AllRows", each Table.FillUp(Table.ReplaceValue(_, each [Result], each if [Result] = null then null else if [Result] = "Complete" then "Training Complete" else "In Training", Replacer.ReplaceValue, {"Result"}), {"Result"}), type table}}),
        #"Expanded AllRows" = Table.ExpandTableColumn(Custom2, "AllRows", {"TrainingStatus DateTime", "Training Status", "Desired Result", "Result"}, {"TrainingStatus DateTime", "Training Status", "Desired Result", "Result"}),
        #"Changed Type1" = Table.TransformColumnTypes(#"Expanded AllRows",{{"TrainingStatus DateTime", type datetime}, {"Training Status", type text}, {"Desired Result", type text}, {"Result", type text}})
    in
        #"Changed Type1"
  • let
        status = [Complete = "Training Complete"],
        Source = your_data,
        group = Table.Group(
            Source, 
            {"Employee Name", "Training"}, 
            {
                {"rows", each _}, 
                {"status", (x) => Record.FieldOrDefault(status, Table.Max(x, "TrainingStatus DateTime")[Training Status], "In Training")}
            }
        ),
        result = Table.ExpandTableColumn(group, "rows", {"TrainingStatus DateTime", "Training Status"})
    in
        result
    • bernate's avatar
      bernate
      Helper III

      Thank you, I ended up using your code as the solution.

  • Here's a somewhat different method that seems to execute more rapidly. All of the transformations are done within the Table.Group aggregation:

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WclTSUfJJTUxJLSrOyCwAcsz0jUz0jQyMTBUMDa0MDIAiwSWJRSWpKUqxOkQp98xTCCjKTy9KLS4mQoshSItzfm5BTmpJKlw9UCC3NC8zObEkMz8PQ4spFkcR1oHuLieCuozQ7CGoA6v/CeoyskAPAie8QWaMHilEKMfmKDxazNBd5Iw/EtFjhAjl6C5yJhhM2CwhrAPFnlgA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Employee Name" = _t, Training = _t, #"TrainingStatus DateTime" = _t, #"Training Status" = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{
                            {"Employee Name", type text}, {"Training", type text}, 
                            {"TrainingStatus DateTime", type datetime}, 
                            {"Training Status", type text}}),
        
        #"Grouped Rows" = Table.Group(#"Changed Type", {"Employee Name", "Training"}, {
            {"Desired Result", (t)=>
                [a=Table.Sort(t, each [TrainingStatus DateTime]),
                 b=Table.DuplicateColumn(a,"Training Status","Desired Result"),
                 c=Table.ReplaceValue(
                     b,
                     each [Training Status],
                     List.Last(b[Training Status]),
                     (x,y,z) as text => if z="Complete" then "Training Complete"
                                        else if z="In Progress" then "In Training"
                                        else z,
                    {"Desired Result"})][c],
                    type table[TrainingStatus DateTime=date, Training Status=text, Desired Result=text]
            }}),
    
        #"Expanded Desired Result" = Table.ExpandTableColumn(#"Grouped Rows", "Desired Result", {"TrainingStatus DateTime", "Training Status", "Desired Result"})
    in
        #"Expanded Desired Result"

     

     

     

    • bernate's avatar
      bernate
      Helper III

      Thank you, this worked for me too. Is there a way to see the performance of a table in Power Query to determine if a methd is more efficient?

      • ronrsnfld's avatar
        ronrsnfld
        Super User

        In the power query editor on power bi there is a diagnostic tools tab which lets you do that. When I checked the small amount of data in your sample executed in a quarter of the time as the accepted. But it's not always reliable. You should compare on your large data set.

  • Hi bernate 

    Here is your solution using DAX.

    1. Create first calculated column using below dax.

    LatestDateTime =
    CALCULATE(
        MAX('Table'[TrainingStatus DateTime]),
        ALLEXCEPT('Table', 'Table'[Employee Name], 'Table'[Training])
    )
     
    2. Create second calculated column using below dax.

    LatestStatus =
    CALCULATE(
        MAX('Table'[Training Status]),
        FILTER(
            ALLEXCEPT('Table', 'Table'[Employee Name], 'Table'[Training]),
            'Table'[TrainingStatus DateTime] = [LatestDateTime]
        )
    )
     
    3. Create final calculated column uisng below dax.

    Desired Result =
    IF(
        [LatestStatus] = "Complete",
        "Training Complete",
        "In Training"
    )
     
     

     

    If this answers your questions, kindly accept it as a solution and give kudos
    • bernate's avatar
      bernate
      Helper III

      Thank you for this alternate method. I ended up using the Power Query solution for efficiency since my table is well over 1 million rows.