Inherited Value in a Parent Child Pattern

Last modified date

Comments: 0

In the previous post in this series we created a Parent Child hierarchy using a Dax Pattern from SQLBI. There are times it is useful to calculate an inherited value from parent item to child. The assigned to person on a User Story to be passed onto the child tasks that are not assigned to anyone, the target date of a feature to be passed down to the child user story and then onto the child tasks. The child items need to be completed before the parent target date.

Power BI and DevOps

This post is part of a series

The Logic

We are going to add this as a calculated column into the work items table. If you were doing this by hand you would go through the items in the path column in reverse, looking up each target date until you found a non-blank one. In DAX we do this by creating a table of the WorkItemIDs in the path and looking up their target dates. Then we filter to only rows with target dates and take the first one.

Inherited Value DAX

Lets work through an example.

WorkItem 46 has an ItemPath of 38|39|45|46, which means it has a Path length of 4. So we start by using GENERATESERIES to create a column 1-4

GENERATESERIES(  1 , PATHLENGTH( WorkItems[ItemPath] ), 1 )
Value
1
2
3
4

We put that inside a GENERATE function and use PATHITEMREVERSE to get the work item ids from the path and then LOOKUP to use that WorkItemID to get the TargetDate of each item. GENERATE function and nested VARs is one of my favourite combinations.

VAR tabWorkItems = 
    GENERATE(
        GENERATESERIES(  1 , PATHLENGTH( WorkItems[ItemPath] ), 1 ),
        VAR tableRow = [Value]
        VAR _WorkItemID = VALUE( PATHITEMREVERSE( WorkItems[ItemPath] , tableRow ) )
        VAR _TargetDate = LOOKUPVALUE( WorkItems[TargetDate] , WorkItems[WorkItemId] , _WorkItemID )
        RETURN ROW ( 
            "WorkItemID",_WorkItemID,
            "TargetDate",_TargetDate
        )
    )
ValueWorkItemIDTargetDate
146
245
3392024-09-09
4382024-11-1

Then we filter the table to rows with a TargetDate and take the first row ordered by Value. This gives us one row of data.

VAR tabFiltered =
    TOPN( 
        1,
        FILTER(tabWorkItems,[TargetDate]>BLANK()),
        [Value],ASC
    )
ValueWorkItemIDTargetDate
3392024-09-09

Finally we use MINX to extract the TargetDate of that single row. The final calculated column DAX looks like this.

Inherited Target Date = 
// Create a table of Value, WorkitemID and TargetDate
VAR tabWorkItems = 
    GENERATE(
        GENERATESERIES(  1 , PATHLENGTH( WorkItems[ItemPath] ), 1 ),
        VAR tableRow = [Value]
        VAR _WorkItemID = VALUE( PATHITEMREVERSE( WorkItems[ItemPath] , tableRow ) )
        VAR _TargetDate = LOOKUPVALUE( WorkItems[TargetDate] , WorkItems[WorkItemId] , _WorkItemID )
        RETURN ROW ( 
            "WorkItemID",_WorkItemID,
            "TargetDate",_TargetDate
        )
    )
// Take the first row of the filtered to non-blank
VAR tabFiltered =
    TOPN( 
        1,
        FILTER(tabWorkItems,[TargetDate]>BLANK()),
        [Value],ASC
    )
// Return the Target Date
VAR Result = MINX( tabFiltered , [TargetDate] )
RETURN Result
Table showing WorkItemId, Title, TargetDate and Inherited Target Date for items 38,39,45 and 46

Inherited Value Conclusion

The Parent Child pattern is very useful and adding in the inherited values adds extra possibilities. I wanted to be able to identify the child items that were making the parent items late.

References

This post builds on the last post in this series and using the SQLBI Parent Child found at https://www.daxpatterns.com/parent-child-hierarchies/.

Over 20 year experience at being passionate about training, solving problems and loving a new challenge especially in the Microsoft's Power Platform suite.

Leave a Reply

Your email address will not be published. Required fields are marked *

Post comment