Forum Discussion

mike_asplin's avatar
mike_asplin
Icon for Helper V rankHelper V
9 months ago
Solved

Surprisingly slow measure

Hi. Looking for some advice to speed up this measure which is surprsingly slow

 

FTEs Purchased new = AVERAGEX(ADDCOLUMNS(SUMMARIZE(DateTable,DateTable[MonthYear]),
                                      "FTE",SUMX(SUMMARIZE(Client,Client[Client ID],Client[FTE Prev 30 days]),
                                                 Client[FTE Prev 30 days]*[Distinct Paying Clients ex Canc])),
                                       [FTE])  

 

Client[FTE Prev 30 days] is a clauted column for each client so is pre calculated.  [Distinct Paying clients ex Calc] is looking at a table of booking and counting the distinct clients. This measure on its own takes 113ms, but the FTEs Purchased measure takes1473 ms?

 

Adding the summarize to the client table improved it a tiny bit.  I reduced the date table down to only be from 1/1/25 but that made no difference. The calcuation is monthly, but these times are for a single month. 

 

Just seems suprisingly long when the only thnig its calcuating is quick and then summing a table of clients that is about 150-200 clients

 

Thanks any suggestions as cant publish it without exceeding the online resources if have more than a couple of months. 

  • Hi mike_asplin ,

    Thanks for sharing the PBIX file.

    Please try the following version of the measure. It keeps the same calculation logic as your original approach but removes the use of SUMMARIZE and ADDCOLUMNS, which are contributing to the performance issue:

    AVERAGEX (
        VALUES ( DateTable[MonthYear] ),
        SUMX (
            VALUES ( Client[Client ID] ),
            CALCULATE (
                MAX ( Client[FTE Prev 30 days] )
                    * [Distinct Paying Clients ex Canc]
            )
        )
    )

    This also avoids the “single value cannot be determined” error by explicitly resolving the client level FTE value.

     

    Attached pbix file for reference.

    Hope this helps.
    Please reach out for further assistance.
    Thank you.

15 Replies

  • mike_asplin Can you try the below DAX and see if it helps. ?

    FTEs Purchased 1 =
    AVERAGEX(
        ADDCOLUMNS(
            SUMMARIZECOLUMNS(
                DateTable[MonthYear],
                Client[Client ID],
                "FTE Contribution", Client[FTE Prev 30 days] * [Distinct Paying Clients ex Canc]
            ),
            "FTE", [FTE Contribution]
        ),
        [FTE])

     

    • mike_asplin's avatar
      mike_asplin
      Icon for Helper V rankHelper V

      Unfortunately its errors A single value of [FTE Prev 30 days] in table clients cant be found. 

       

      There are 3 dates

      Datetable

      Booking in which the date of the booking is related to the datetable

      Clients in which the client ID is related to the bookings.

       

      I am calculating essential the number of Employees each client needed each day (sometimes 1 or might be 2) made in prev 30 days and storing it as a column on the client table.

       

      I then need to calculate how many employees were needed in the month by summing the product of the column for each client that was active in the month and repeat that for previous months. Hence the SUMX over clients and the AverageX over the Monthyear.  

       

      Can you use summarizecolumns when there is no relationship between Datetable and clients? I guess not. 

       

       

       

      • Ashish_Mathur's avatar
        Ashish_Mathur
        Icon for Super User rankSuper User

        Hi,

        Share some dummy data to work with.  Show the expected result.

  • Avoid nested SUMMARIZE/ADDCOLUMNS/SUMX—iterate directly over months or clients.

    Move measures out of row context if possible.

    Use VALUES or SUMMARIZECOLUMNS instead of SUMMARIZE + ADDCOLUMNS to reduce repeated calculations.

    Aggregate at the month level first instead of calculating for each client within each month.

    If this response was helpful, please accept it as a solution and give kudos to support other community member.

    Regards,
    Rufyda Rahma | MIE

     

  • Hi mike_asplin 

     

    FTEs Purchased Optimized  =
    VAR MonthlyData =
    SUMMARIZECOLUMNS(
    // Bring in the MonthYear for grouping
    DateTable[MonthYear],
    // Also bring in Client ID to get the correct filter for [Distinct Paying Clients ex Canc]
    Client[Client ID],
    // The filter from DateTable[MonthYear] is now active for the measure
    "Weighted FTE",
    VAR CurrentClientFTE = SELECTEDVALUE(Client[FTE Prev 30 days])
    // This measure now evaluates in a context filtered by both Date[MonthYear] AND Client[ID]
    VAR ClientsForMonth = [Distinct Paying Clients ex Canc]
    RETURN
    CurrentClientFTE * ClientsForMonth
    )
    // Now sum the weighted FTE for each month and then average
    VAR MonthlyTotals =
    ADDCOLUMNS(
    VALUES(DateTable[MonthYear]),
    "Monthly Total",
    CALCULATE(
    SUMX(
    FILTER(MonthlyData, [MonthYear] = EARLIER([MonthYear])),
    [Weighted FTE]
    )
    )
    )
    RETURN
    IF(
    NOT ISEMPTY(MonthlyTotals),
    AVERAGEX(MonthlyTotals, [Monthly Total]),
    BLANK()
    )

     

    Can you please check and confirm. Thank You!

    • mike_asplin's avatar
      mike_asplin
      Icon for Helper V rankHelper V

      Hi.

       

      Unfortunately it throws an error in this bit EARLIER refers to an earlier row context which doesnt exist

       

      VAR MonthlyTotals =
      ADDCOLUMNS(
      VALUES(DateTable[MonthYear]),
      "Monthly Total",
      CALCULATE(
      SUMX(
      FILTER(MonthlyData, [MonthYear] = EARLIER([MonthYear])),
      [Weighted FTE]
      )

       

      I understand what you are doing an it all makes sense so pity it doesnt work. 

  • Your measure is slow because it’s doing nested iterator work (AVERAGEX → ADDCOLUMNS → SUMX over a SUMMARIZE) and, crucially, it’s forcing [Distinct Paying Clients ex Canc] to be evaluated many times (once per month and per client row context you create). That “113ms alone” becomes 113ms × N evaluations.

     

    A much faster pattern is: iterate clients once, and let the date/month context come from the visual (or an outer CALCULATE), instead of building a MonthYear table inside the measure.

     

    Try this rewrite:

    FTEs Purchased =
    AVERAGEX (
        VALUES ( DateTable[MonthYear] ),
        VAR PayingClients = [Distinct Paying Clients ex Canc]
        RETURN
            SUMX (
                VALUES ( Client[Client ID] ),
                Client[FTE Prev 30 days] * PayingClients
            )
    )

     

    • mike_asplin's avatar
      mike_asplin
      Icon for Helper V rankHelper V

      Sorry throws an error single value ofr [FTE prev 30 days] in table client cannot be determined

  • Sorry took a while to cut down the size of the data

     

    Under Metrics/FTE are my previous attempts

     

    [total FTE Purchased] calculates on the fly for every month but it is only marginally slower than

     

    [FTEs Puchased new] which calcuates the last 30 days FTE as a column on client table and uses that for every month. Less accurate, but i thought it would be much quicker. 

     

    [FTE purchased Optimized]is stuck up in ABV folder as cant move it 

     

    File is here   https://www.dropbox.com/scl/fi/z3ml56s8habcc2k4q9py0/Trinity-PowerBI-test.pbix?rlkey=2q2qnqy4qliyofyv8qbz72av7&dl=0

     

    Thanks for any advice

    • v-veshwara-msft's avatar
      v-veshwara-msft
      Icon for Community Support rankCommunity Support

      Hi mike_asplin ,

      Thanks for sharing the PBIX file.

      Please try the following version of the measure. It keeps the same calculation logic as your original approach but removes the use of SUMMARIZE and ADDCOLUMNS, which are contributing to the performance issue:

      AVERAGEX (
          VALUES ( DateTable[MonthYear] ),
          SUMX (
              VALUES ( Client[Client ID] ),
              CALCULATE (
                  MAX ( Client[FTE Prev 30 days] )
                      * [Distinct Paying Clients ex Canc]
              )
          )
      )

      This also avoids the “single value cannot be determined” error by explicitly resolving the client level FTE value.

       

      Attached pbix file for reference.

      Hope this helps.
      Please reach out for further assistance.
      Thank you.

      • v-veshwara-msft's avatar
        v-veshwara-msft
        Icon for Community Support rankCommunity Support

        Hi mike_asplin ,
        Just wanted to check if the response provided was helpful. If further assistance is needed, please reach out.
        Thank you.

  • Hi mike_asplin ,
    Just wanted to check if any of the responses provided were helpful. If further assistance is needed, please reach out.
    Thank you.