AVERAGEX iterating over one table with calculation on another

dicken

Active Member
Joined
Feb 12, 2022
Messages
292
Office Version
  1. 365
Platform
  1. Windows
Sorry for a poor description, essentially in the scenario the granularity of an average was changed by iterating over the linked date table;

So to start you have ;
SQL:
 Average M:=AVERAGEX(fTransactions,[Total Revenue Iterate Over Fact])

Fine, but do change the granularity this then becomes
VBA Code:
AVERAGEX(VALUES(dDate[Year Month]),[Total Revenue Iterate Over Fact])

But the total revenue measure is ;

Excel Formula:
    Total Revenue Iterate Over Fact:=SUMX(fTransactions,fTransactions[UnitsSold]*RELATED(dProduct[RetailPrice]))

So my question , at last is how can I incorrporate the abvoe code into the AVERAGEX formula iterating over the date table and not use the measure,

I've tried various options none of which work,
VBA Code:
  AVERAGEX( VALUES(dDate[Year Month]),CALCULATE(SUM(fTransactions[UnitsSold])*dProduct[RetailPrice]))

The clsoeset I've got is
VBA Code:
  AVERAGEX( VALUES(dDate[Year Month]),SUMX(fTransactions,fTransactions[UnitsSold]*RELATED(dProduct[RetailPrice])))

Which I knew wouldn't work but at least gave an answer, it must be possible or it wouldn't work with the measure?
What am I overlooking , getting wrong?

Richard.
 

Excel Facts

Copy a format multiple times
Select a formatted range. Double-click the Format Painter (left side of Home tab). You can paste formatting multiple times. Esc to stop
I haven’t seen the model, but my guess is this.
Rich (BB code):
=
AVERAGEX (
    VALUES ( dDate[Year Month] ),
    SUMX (
        VALUES ( dProduct[RetailPrice] ),
        CALCULATE (
            SUM ( fTransactions[UnitsSold] )
        ) * dProduct[RetailPrice]
    )
)
 
Upvote 0
I haven’t seen the model, but my guess is this.
Rich (BB code):
=
AVERAGEX (
    VALUES ( dDate[Year Month] ),
    SUMX (
        VALUES ( dProduct[RetailPrice] ),
        CALCULATE (
            SUM ( fTransactions[UnitsSold] )
        ) * dProduct[RetailPrice]
    )
)
Well it was a very good guess,
So the AVERAGEX iterates over the unique Date Year 'table',
SUMX is iterating over the product table; I think CALCULATE is enables the entire Data mode to be seen and causes the
filter context for each 'row' of units sold * price ?

In my simplistic way I did try


Excel Formula:
Copy of Using Formula :=
AVERAGEX (
    VALUES ( dDate[Year Month] ),
    SUMX (
        fTransactions,
        fTransactions[UnitsSold] * RELATED ( dProduct[RetailPrice] )
    )
)

But this just returns the total, any further information or reading suggestions alway welcome.

Richard.
 
Upvote 0
It's a long journey, but you are well underway.

Yes, the CALCULATE in my formula forces context transition for each row in the iteration. Here is pseudo code

Code:
total = 0
result for this row = 0

for r = 1 to <number of rows in table>
   Filter the dimension table for row = r
   propagate the filters from the dimension table to the fact table (using CALCULATE)
   result for this row = sum(fact[column])  'of the now filtered fact table
   total = total + result for this row
next r

return total

If you don't use calculate, you get the following pseudo code

Code:
total = 0
result for this row = 0

for r = 1 to <number of rows in table>
   don't filter the dimension table for row = r
   don't propagate the filters from the dimension table to the fact table, because you didn't specify this behaviour
   result for this row = sum(fact[column])  'of the entire unfiltered fact table
   total = total + result for this row 'which is the entire table for each row in the iteration
next r

return total (which is <number of row in table> * SUM(unfiltered fact table)

The issues with your formula are
  1. You are missing the CALCUALTE to force context transition.
  2. You are iterating the fact table when it is better to iterate the dimension table (as a general rule, aim for the smallest table).
This should work, but mine is still more efficient.

Code:
Copy of Using Formula :=
AVERAGEX (
    VALUES ( dDate[Year Month] ),
    CALCULATE(SUMX (
        fTransactions,
        fTransactions[UnitsSold] * RELATED ( dProduct[RetailPrice] )
    ))
)

Technically, in my formula I am iterating the Price column (converted to table by VALUES), not the product table. Often, but not always, this is a smaller (virtual) table than the dimension table itself.

Further reading
 
Upvote 0
It's a long journey, but you are well underway.

Yes, the CALCULATE in my formula forces context transition for each row in the iteration. Here is pseudo code

Code:
total = 0
result for this row = 0

for r = 1 to <number of rows in table>
   Filter the dimension table for row = r
   propagate the filters from the dimension table to the fact table (using CALCULATE)
   result for this row = sum(fact[column])  'of the now filtered fact table
   total = total + result for this row
next r

return total

If you don't use calculate, you get the following pseudo code

Code:
total = 0
result for this row = 0

for r = 1 to <number of rows in table>
   don't filter the dimension table for row = r
   don't propagate the filters from the dimension table to the fact table, because you didn't specify this behaviour
   result for this row = sum(fact[column])  'of the entire unfiltered fact table
   total = total + result for this row 'which is the entire table for each row in the iteration
next r

return total (which is <number of row in table> * SUM(unfiltered fact table)

The issues with your formula are
  1. You are missing the CALCUALTE to force context transition.
  2. You are iterating the fact table when it is better to iterate the dimension table (as a general rule, aim for the smallest table).
This should work, but mine is still more efficient.

Code:
Copy of Using Formula :=
AVERAGEX (
    VALUES ( dDate[Year Month] ),
    CALCULATE(SUMX (
        fTransactions,
        fTransactions[UnitsSold] * RELATED ( dProduct[RetailPrice] )
    ))
)

Technically, in my formula I am iterating the Price column (converted to table by VALUES), not the product table. Often, but not always, this is a smaller (virtual) table than the dimension table itself.

Further reading
Thanks once again,

RD
 
Upvote 0
I haven’t seen the model, but my guess is this.
Rich (BB code):
=
AVERAGEX (
    VALUES ( dDate[Year Month] ),
    SUMX (
        VALUES ( dProduct[RetailPrice] ),
        CALCULATE (
            SUM ( fTransactions[UnitsSold] )
        ) * dProduct[RetailPrice]
    )
)
I know this was a while ago but am I correct in thinking the CALCULATE, is needed because if I were using a measure there would be an implicit calculate already there?

Richard
 
Upvote 0

Forum statistics

Threads
1,223,886
Messages
6,175,194
Members
452,616
Latest member
intern444

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top