Forum Discussion
XELANAMYT
1 year agoFrequent Visitor
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...
- 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 OutputThe 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.
ronrsnfld
Super User
1 year agoPerhaps this is what you want from your posted data:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcnRyVtJRMgRiA0N9IDIyMDAAchwLCnJSlWJ1YAqMkBWAVDvlJCZnJ6UWFVUiqTJGVmWES5UJulnOpcmluUBVSGpMiTLJDN3ZWFWZo5vlkphbnJ8HVuHi6obufUMU70MUGOEIn1gA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ObjectId = _t, Revision = _t, ADate = _t, Category = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ObjectId", type text}, {"Revision", Int64.Type}, {"ADate", type date}, {"Category", type text}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"ObjectId","Category"}, {
{"all", each Record.SelectFields(Table.First(_),{"Revision","ADate"}), type[Revision=Int64.Type, ADate=date] }},
GroupKind.Local,(x,y)=>(Number.From((x[Category]<>y[Category]) or (x[ObjectId]<>y[ObjectId])) )),
#"Expanded all" = Table.ExpandRecordColumn(#"Grouped Rows", "all", {"Revision", "ADate"}, {"Revision", "ADate"}),
#"Grouped Rows1" = Table.Group(#"Expanded all", {"ObjectId", "Category"}, {
{"all", each Record.SelectFields(Table.Last(_),{"Revision","ADate"}), type [Revision=number, ADate=date]}}),
#"Expanded all1" = Table.ExpandRecordColumn(#"Grouped Rows1", "all", {"Revision", "ADate"}, {"Revision", "ADate"})
in
#"Expanded all1"