Forum Discussion

XELANAMYT's avatar
XELANAMYT
Frequent Visitor
1 year ago
Solved

Finding the first record in the latest group

I have a set of data which can be grouped by a Category for each Object, however I need to find the latest grouping, currently I can narrow it down to all the groups, but not the latest. I appreciate...
  • AmiraBedh's avatar
    1 year ago

    Hello !

    Thank you for posting on MS Fabric community.

    This is the dataset I used as an example :

     

    If you want to use Power Query, I detailed the major steps in this code :

    let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcnRyVtJRMgRix4KCnFSlWB2YmBEQO+UkJmcnpRYVVSJJGOOSMAFi59Lk0lygBJKwKS71ZrgkzIHYJTG3OD8PLOji6obhRoiYEUIsFgA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ObjectId = _t, Revision = _t, Category = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"ObjectId", type text}, {"Revision", Int64.Type}, {"Category", type text}}),
    
        /* Sort by ObjectId then Revision so rows are in logical order */
        #"Sorted Rows" =
            Table.Sort(#"Changed Type", {{"ObjectId", Order.Ascending}, {"Revision", Order.Ascending}}),
    
        /* Add an Index to compare each row with the previous one */
        #"Added Index"           = Table.AddIndexColumn(#"Sorted Rows", "Index", 1, 1, Int64.Type),
        #"Added PrevIndex"       = Table.AddColumn(#"Added Index", "PrevIndex", each [Index]-1, Int64.Type),
    
        /* Pull the previous row Category & ObjectId */
        #"Merged PrevRow" =
            Table.NestedJoin(
                #"Added PrevIndex",
                {"PrevIndex"},
                #"Added Index",
                {"Index"},
                "PrevRow",
                JoinKind.LeftOuter
            ),
        #"Expanded PrevRow" =
            Table.ExpandTableColumn(
                #"Merged PrevRow",
                "PrevRow",
                {"ObjectId", "Category"},
                {"PrevObjectId", "PrevCategory"}
            ),
    
        /* Flag the start of a new contiguous group (1 = new group) */
        #"Add GroupStart" =
            Table.AddColumn(
                #"Expanded PrevRow",
                "GroupStart",
                each if [ObjectId] = [PrevObjectId] and [Category] = [PrevCategory] then 0 else 1,
                Int64.Type
            ),
    
        /* Create a running GroupID per ObjectId */
        #"Add GroupID" =
            Table.AddColumn(
                #"Add GroupStart",
                "GroupID",
                each
                    List.Sum(
                        Table.SelectRows(
                            #"Add GroupStart",
                            (r) => r[ObjectId] = [ObjectId] and r[Index] <= [Index]
                        )[GroupStart]
                    ),
                Int64.Type
            ),
    
        /*  For every ObjectId, keep only rows that belong to the latest GroupID */
        LatestGroupPerObject =
            let
                MaxGroups =
                    Table.Group(
                        #"Add GroupID",
                        {"ObjectId"},
                        {{"MaxGroupID", each List.Max([GroupID]), Int64.Type}}
                    )
            in
                Table.NestedJoin(
                    #"Add GroupID",
                    {"ObjectId", "GroupID"},
                    MaxGroups,
                    {"ObjectId", "MaxGroupID"},
                    "J",
                    JoinKind.Inner
                ),
    
        /* Within each latest-group keep only the first Revision */
        #"Keep First of Each Latest" =
            Table.SelectRows(
                Table.Sort(LatestGroupPerObject, {{"Revision", Order.Ascending}}),
                (row) =>
                    row[Revision]
                        = List.Min(
                            Table.SelectRows(
                                LatestGroupPerObject,
                                (r) => r[ObjectId] = row[ObjectId] and r[GroupID] = row[GroupID]
                            )[Revision]
                        )
            ),
    /*  Finally keep just the three original columns */
        Output =
            Table.SelectColumns(#"Keep First of Each Latest", {"ObjectId", "Revision", "Category"})
    in
        Output

    The output is :

     

    If you want the solution in DAX, I created 3 calculated columns, the 1st one to flag where a new group starts,

    the 2nd one is to run the GroupID per ObjectId and the 3rd one to identify the 1st row of the latest group :

     

    GroupStart = 
    VAR PrevCat =
        CALCULATE (
            MAX ( 'Table B'[Category] ),
            FILTER (
                'Table B',
                'Table B'[ObjectId] = EARLIER ( 'Table B'[ObjectId] )
                    && 'Table B'[Revision] = EARLIER ( 'Table B'[Revision] ) - 1
            )
        )
    RETURN IF ( PrevCat = 'Table B'[Category], 0, 1 )
    
    
    
    GroupID = 
    CALCULATE (
        SUM ( 'Table B'[GroupStart] ),
        FILTER (
            'Table B',
            'Table B'[ObjectId] = EARLIER ( 'Table B'[ObjectId] )
                && 'Table B'[Revision] <= EARLIER ( 'Table B'[Revision] )
        )
    )
    
    
    IsFirstOfLatest = 
    VAR LatestGroup =
        CALCULATE ( MAX ( 'Table B'[GroupID] ), ALLEXCEPT ( 'Table B', 'Table B'[ObjectId] ) )
    VAR MinRevisionInLatest =
        CALCULATE (
            MIN ( 'Table B'[Revision] ),
            FILTER ( 'Table B', 'Table B'[ObjectId] = EARLIER ( 'Table B'[ObjectId] ) && 'Table B'[GroupID] = LatestGroup )
        )
    RETURN
        IF ( 'Table B'[GroupID] = LatestGroup && 'Table B'[Revision] = MinRevisionInLatest, 1, 0 )
    

     

    In your visual you will need to use IsFirstOfLatest as filter to select only the rows having the value of 1 for that CC :

     

    I attached the pbix file with the solution.