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

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
Gbdate
Frequent Visitor

Help for calculating overlapping periods

Guys, I have a relatively complicated task, I need to calculate some maintenance indicators (Downtime and Availability). The problem is that there are overlapping failures, where I can't perform these calculations line by line. 

 

I would like to establish a dax where it is possible to calculate the CORRECT availability of the equipment, even when there are overlapping failures.

 

Dataset

DatasetDataset

Added calculated columns

Add Calculated Columns KPI'sAdd Calculated Columns KPI's

Where:

Worktime = Today - Start_work

Downtime = End_failure - Start_failure

Availability = 1-(downtime/worktime)

 

Here I perform the creation of two measures to calculate the availability KPI. But since I'm simply calculating line by line and WITHOUT disregarding overlaps, my final results are wrong.

KPIS's final calculationKPIS's final calculation

 

Failure and overlap scheme

Overlapping failures and downtimesOverlapping failures and downtimes

1 ACCEPTED SOLUTION

Hi  @Gbdate ,

 

First create an index column;

Then create 3 columns below:

Mark =
VAR _previousend =
    CALCULATE (
        MAX ( 'Table'[End_failure] ),
        FILTER (
            'Table',
            'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
                && 'Table'[Index]
                    = EARLIER ( 'Table'[Index] ) - 1
        )
    )
RETURN
    IF ( 'Table'[Start_failure] < _previousend, 1, 0 )
Downtime =
VAR _minindex =
    CALCULATE (
        MIN ( 'Table'[Index] ),
        FILTER ( 'Table', 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] ) )
    )
VAR _nextmark1 =
    CALCULATE (
        MAX ( 'Table'[Mark] ),
        FILTER (
            'Table',
            'Table'[Index] = _minindex + 1
                && 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
        )
    )
VAR _index1 =
    CALCULATE (
        MAX ( 'Table'[Index] ),
        FILTER (
            'Table',
            'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
                && 'Table'[Index] < EARLIER ( 'Table'[Index] )
                && 'Table'[Mark] = 0
        )
    )
VAR _start =
    CALCULATE (
        MAX ( 'Table'[Start_failure] ),
        FILTER (
            'Table',
            'Table'[Index] = _index1
                && 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
        )
    )
VAR _nextmark2 =
    CALCULATE (
        MAX ( 'Table'[Mark] ),
        FILTER (
            'Table',
            'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
                && 'Table'[Index]
                    = EARLIER ( 'Table'[Index] ) + 1
        )
    )
RETURN
    IF (
        'Table'[Mark] = 0,
        IF (
            _nextmark1 = 0,
            DATEDIFF ( 'Table'[Start_failure], 'Table'[End_failure], DAY ),
            IF ( _nextmark1 = 1, 0 )
        ),
        IF (
            'Table'[Mark] = 1,
            IF (
                _nextmark2 = 0,
                DATEDIFF ( _start, 'Table'[End_failure], DAY ),
                IF ( _nextmark2 = 1, 0 )
            )
        )
    )
Availability =
VAR _Worktime =
    DATEDIFF ( 'Table'[Start_work], TODAY (), DAY )
VAR _downtime =
    SUMX (
        FILTER ( 'Table', 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] ) ),
        'Table'[Downtime]
    )
RETURN
    1 - DIVIDE ( _downtime, _Worktime )

 

And you will see:

vkellymsft_0-1632994535897.png

For the related .pbix file,pls see attached.

 

Best Regards,
Kelly

Did I answer your question? Mark my reply as a solution!

View solution in original post

9 REPLIES 9
Gbdate
Frequent Visitor

I thought of solving it as follows:

 

1 - Add three calculated columns (Internal_Failure_ID, Start_failure_acumulated, End_failure_acumulated). Where the "acumulated columns" would calculate the conditions of intersection between failures of the same equipment, thus generating the "Internal_ID_Failure".

 

2 - It would only consider faults with "Internal_ID_Failure" distinct for the final calculation of the availability KPI, calculating its unavailability using the following formula:

 

Availability = 1 -Unavailability (days)

 

and

 

Unavailability (days) = Downtime (days) / Worktime (days)

 

But I can't run the dax of this scheme.

 

Do you have any idea how to do this in dax?

 

Esquema de calculo.png

 

            KPI's final.png

 

 

 

CNENFRNL
Community Champion
Community Champion

Fairly easy to combine overlapping lists in PQ,

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("fY5LCsAgDAXv4lrIR6112QuU7sX7X6PRWFr7AxcDb4iTs1kXdMYaAgJGmk9MDYMgkyn2zZza3E3yf6og1h2FE3C8uFuKVUCV78zg9MaXC+yPT4L2fLsM8nqxG4uftpi6D8VlBw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Equipment = _t, Start_work = _t, Start_failure = _t, End_failure = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Equipment", type text}, {"Start_work", type date}, {"Start_failure", type date}, {"End_failure", type date}}),

    #"Combined Failures" = Table.Group(#"Changed Type", {"Equipment","Start_work"}, {{"Failure", each List.Combine(List.Transform(Table.ToRecords(_), each {Number.From([Start_failure])..Number.From([End_failure])}))}}),
    Availability = Table.AddColumn(#"Combined Failures", "Availability", each let dates = {Number.From([Start_work])..Number.From(Date.From(DateTime.LocalNow()))}, avail = List.Difference(dates, [Failure]) in List.Count(avail) / List.Count(dates), Percentage.Type)
in
    Availability

Screenshot 2021-09-28 052244.png


Thanks to the great efforts by MS engineers to simplify syntax of DAX! Most beginners are SUCCESSFULLY MISLED to think that they could easily master DAX; but it turns out that the intricacy of the most frequently used RANKX() is still way beyond their comprehension!

DAX is simple, but NOT EASY!

Ty 

Hi  @Gbdate ,

 

First create an index column;

Then create 3 columns below:

Mark =
VAR _previousend =
    CALCULATE (
        MAX ( 'Table'[End_failure] ),
        FILTER (
            'Table',
            'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
                && 'Table'[Index]
                    = EARLIER ( 'Table'[Index] ) - 1
        )
    )
RETURN
    IF ( 'Table'[Start_failure] < _previousend, 1, 0 )
Downtime =
VAR _minindex =
    CALCULATE (
        MIN ( 'Table'[Index] ),
        FILTER ( 'Table', 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] ) )
    )
VAR _nextmark1 =
    CALCULATE (
        MAX ( 'Table'[Mark] ),
        FILTER (
            'Table',
            'Table'[Index] = _minindex + 1
                && 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
        )
    )
VAR _index1 =
    CALCULATE (
        MAX ( 'Table'[Index] ),
        FILTER (
            'Table',
            'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
                && 'Table'[Index] < EARLIER ( 'Table'[Index] )
                && 'Table'[Mark] = 0
        )
    )
VAR _start =
    CALCULATE (
        MAX ( 'Table'[Start_failure] ),
        FILTER (
            'Table',
            'Table'[Index] = _index1
                && 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
        )
    )
VAR _nextmark2 =
    CALCULATE (
        MAX ( 'Table'[Mark] ),
        FILTER (
            'Table',
            'Table'[Equipament] = EARLIER ( 'Table'[Equipament] )
                && 'Table'[Index]
                    = EARLIER ( 'Table'[Index] ) + 1
        )
    )
RETURN
    IF (
        'Table'[Mark] = 0,
        IF (
            _nextmark1 = 0,
            DATEDIFF ( 'Table'[Start_failure], 'Table'[End_failure], DAY ),
            IF ( _nextmark1 = 1, 0 )
        ),
        IF (
            'Table'[Mark] = 1,
            IF (
                _nextmark2 = 0,
                DATEDIFF ( _start, 'Table'[End_failure], DAY ),
                IF ( _nextmark2 = 1, 0 )
            )
        )
    )
Availability =
VAR _Worktime =
    DATEDIFF ( 'Table'[Start_work], TODAY (), DAY )
VAR _downtime =
    SUMX (
        FILTER ( 'Table', 'Table'[Equipament] = EARLIER ( 'Table'[Equipament] ) ),
        'Table'[Downtime]
    )
RETURN
    1 - DIVIDE ( _downtime, _Worktime )

 

And you will see:

vkellymsft_0-1632994535897.png

For the related .pbix file,pls see attached.

 

Best Regards,
Kelly

Did I answer your question? Mark my reply as a solution!

Thank you ! Your code really helped me a lot.

 

I just made small adjustments to better fit my data.  

Hi  @Gbdate ,

 

Glad to help.

 

Best Regards,
Kelly

Did I answer your question? Mark my reply as a solution!

Guys, I need one more help from you. I'm stuck in the following situation: I need to create the following columns calculated in DAX, can you help me one more time? 🙂 

 

Dataset and calculated columns.Dataset and calculated columns.

 https://docs.google.com/spreadsheets/d/1MuBf0FjDIUiPqBA3A4oU-DJFY-oD-KEX/edit?usp=sharing&ouid=11793... 

Failures Dataset2Failures Dataset2

 

Hi  @Gbdate ,

 

Glad to help.

But would you pls create a new thread for us to follow?

 

Best Regards,
Kelly

Did I answer your question? Mark my reply as a solution!

For sure! I will be very grateful if you can help me one more time :). Below is the link to the new post:

https://community.powerbi.com/t5/Desktop/Help-for-creating-calculated-columns-adjustments-for-overla...

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.