Forum Discussion
Finding the first record in the latest group
- 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.
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.
I've updated my question as I don't think it was clear enough.