Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Be one of the first to start using Fabric Databases. View on-demand sessions with database experts and the Microsoft product team to learn just how easy it is to get started. Watch now

Reply
cashewNut
Frequent Visitor

Controlling filter context in percentile calculation

I am struggling to control different filter context transitions within a complex dax measure. I am trying to compute the median duration for a certain percentile of events, where that percentile is partitioned within a table. My table is structured like this:

index     opportunity_id  event_order   duration  status   date

109750a1120Active (Not Recruiting)24/01/2023 00:00
86263b1361Active (Not Recruiting)12/07/2022 00:00
109752a2134Active (Not Recruiting)07/02/2023 00:00
86264b2361Active (Not Recruiting)12/07/2022 00:00



My strategy has been to calculate the target event order (e.g. the one which is the 25th percentile) partitioned by the opportunity_id, and then calculate the median duration for a table filtered to only include records where the event_order = target:

 

 

 

 

25% Duration (Static) = 

VAR _percentile = 0.25

// compute the 25% percentile event order partitioned by opportunity id
VAR _tbl =

        ADDCOLUMNS (
            'Table',
                "@target",
                    CEILING(
                        CALCULATE (
                            MAX ( 'Table'[event_order]),
                            FILTER (
                                ALL('Table'),
                                'Table'[opportunity_id] = EARLIER ( 'Table'[opportunity_id] )
                            ))
                    * _percentile, 
                1)
            )


VAR  _result =

        MEDIANX(
            FILTER (
            _tbl,
            [event_order] = [@target]
        ), 
        [duration])

RETURN _result

 

 

 

 


This returns the correct results for all visual types. However, the use of ALL() makes it insensitive to external filtering in the right order, which is desired. For example, if applying a certain filter will remove those records from the _tbl result, when what I need is for the new event order and target to be recalculated dynamically.

To enable dynamic filtering I have tried to re-calculate the event_order dynamically within the measure like so

 

 

 

 

25% Duration (dynamic) = 

VAR _percentile = 0.25

// compute the 25% percentile event order partitioned by opportunity id
VAR _tbl =

        ADDCOLUMNS (
            'Table',
                "@target",
                    CEILING(
                        CALCULATE (
                            MAX ( 'Table'[event_order]),
                            FILTER (
                                ALL('Table'),
                                'Table'[opportunity_id] = EARLIER ( 'Table'[opportunity_id] )
                            ))
                    * _percentile, 
                1),
                "@event_order",
                ROWNUMBER(
                    ALLSELECTED('Table'), 
                    ORDERBY([event_order], ASC, [index], ASC), 
                    LAST, 
                    PARTITIONBY([opportunity_id])
)
            )


VAR  _result =

        MEDIANX(
            FILTER (
            _tbl,
            [@event_order] = [@target]
        ), 
        [duration])

RETURN _result

 

 

 

 


This returns the correct results in visuals partitioned by opportunty_id (and allows for external filtering) but as soon as I add a date range it becomes inaccurate because it partitions for each date range in the visual. I.e. it returns the 25th percentile for each date range in which it occurs. 

cashewNut_0-1712653218554.png

 

Is there any way to control the filter context in such a way that it computes accurate results against timelines (i.e. just one 25th percentile event per opportunity) while still respecting filtering that happens at the reporting layer? 

 

1 ACCEPTED SOLUTION

Thanks @v-kongfanf-msft ! I am trying to avoid specifying filters directly in the query. I've ended up getting the query to work in production where I have a relationship to the filtering tables ('Table1') in this example, using a combination of PERCENTILE.INC(), KEEPFILTERS(), and ALLACCEPT()

VAR _percentile =
ADDCOLUMNS (
FILTER (
'Table',
"@target",
CALCULATE (
MINX (
FILTER (
'Table',
[event_order]
>= PERCENTILEX.INC (
VALUES ( 'Table'[event_order] ),
'Table'[event_order],
_percentile
)
),
[event_order]
),
ALLEXCEPT ( 'Table', 'Table[opportunity_id] ),
KEEPFILTERS ( 'TABLE1' ),
)
)
//calculate the median duration for records in a result set limited to the ordering targets
VAR _result =
MEDIANX (
FILTER (
_percentile ,
[_event_order] = [@target]
),
[Duration]
)
RETURN
_result

View solution in original post

2 REPLIES 2
v-kongfanf-msft
Community Support
Community Support

Hi @cashewNut ,

 

Try to modify your formula like below:

25% Duration (Adjusted) = 
VAR _percentile = 0.25
VAR _filteredTable = FILTER(ALLSELECTED('Table'), [status] = "Active (Not Recruiting)")
VAR _partitionedTable = 
    ADDCOLUMNS (
        _filteredTable,
        "@target",
            CEILING(
                CALCULATE (
                    MAX ( 'Table'[event_order]),
                    ALLEXCEPT('Table', 'Table'[opportunity_id])
                ) * _percentile, 
            1)
    )
VAR _result = 
    MEDIANX(
        FILTER (
            _partitionedTable,
            [event_order] = [@target]
        ), 
        [duration]
    )
RETURN _result

 

Best Regards,
Adamk Kong

 

If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Thanks @v-kongfanf-msft ! I am trying to avoid specifying filters directly in the query. I've ended up getting the query to work in production where I have a relationship to the filtering tables ('Table1') in this example, using a combination of PERCENTILE.INC(), KEEPFILTERS(), and ALLACCEPT()

VAR _percentile =
ADDCOLUMNS (
FILTER (
'Table',
"@target",
CALCULATE (
MINX (
FILTER (
'Table',
[event_order]
>= PERCENTILEX.INC (
VALUES ( 'Table'[event_order] ),
'Table'[event_order],
_percentile
)
),
[event_order]
),
ALLEXCEPT ( 'Table', 'Table[opportunity_id] ),
KEEPFILTERS ( 'TABLE1' ),
)
)
//calculate the median duration for records in a result set limited to the ordering targets
VAR _result =
MEDIANX (
FILTER (
_percentile ,
[_event_order] = [@target]
),
[Duration]
)
RETURN
_result

Helpful resources

Announcements
Las Vegas 2025

Join us at the Microsoft Fabric Community Conference

March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount!

Dec Fabric Community Survey

We want your feedback!

Your insights matter. That’s why we created a quick survey to learn about your experience finding answers to technical questions.

ArunFabCon

Microsoft Fabric Community Conference 2025

Arun Ulag shares exciting details about the Microsoft Fabric Conference 2025, which will be held in Las Vegas, NV.

December 2024

A Year in Review - December 2024

Find out what content was popular in the Fabric community during 2024.