Calculate cumulative sum of summarized table column - powerbi

I having trouble calculating the cumulative sum of a column on PowerBI.
I have a big offer table and I want to run a pareto analysis on it. Following many tutorials, I created a SUMMARIZED table by offer and a sum of their sales. So the table definition is:
summary = SUMMARIZE(big_table; big_table[offer]; "offer sales"; sum(big_table[sales]))
Many of the forums and stackoverflow answers I found have direct me to the following formula for cumulative sum on column:
cum_sales =
CALCULATE(
sum([offer_sales]);
FILTER(
ALLSELECTED(summary);
summary[offer_sales] <= max( summary[offer_sales])
)
)
However the resulting table is not correct:
What I need is simply to have the offers ordered by sales descending and then add the current row's sales amount to the previous row's sales,
So I excepted numbers closer to:
1st row: 1.5M
2nd row: 2.1M
3rd row: 2.6M and so on
But (maybe) because of my data structure and (certainly) lack of knowledge on how PowerBI works, I'm not getting the right results...

Total Amount = SUM ( 'Fact'[Amount] )
Offer Visual Cumulative =
VAR OfferSum =
ADDCOLUMNS (
ALLSELECTED ( 'Offer'[Offer] ),
"amt", [Total Amount]
)
VAR CurrentOfferAmount = [Total Amount]
VAR OffersLessThanCurrent =
FILTER (
OfferSum,
[amt] <= CurrentOfferAmount
)
RETURN
SUMX (
OffersLessThanCurrent,
[amt]
)
There's no need to pre-aggregate to a summary table. We can handle that as in the measure above.
This assumes a single fact table named 'Fact', and a table of distinct offers, 'Offer'.
Depending on what you're doing in terms of other filters on 'Offer', you may need to instead do as below:
Offer Visual Cumulative =
VAR OfferSum =
ADDCOLUMNS (
ALLSELECTED ( 'Offer'[Offer] ),
"amt", CALCULATE ( [Total Amount], ALLEXCEPT ( 'Offer', 'Offer'[Offer] ) )
)
...
The rest of the measure would be the same.
The measure is fairly self-documenting in its VARs. The first VAR, OfferSum is a table with columns ('Offer'[Offer], [amt]). This will include all offers displayed in the current visual. CurrentOfferAmount is the amount for the offer on the current row/axis label of the visual. OffersLessThanCurrent takes OfferSum and filters it. Finally, we iterate OffersLessThanCurrent and add up the amounts.
Here's a sample:

Related

RANKX DAX not updating other graph

I've got the following DAX Measure that provides me with the ability to filter down to the last XX of activity from an individual.
I can only seem to add the measure to the Filter on Visual so when chosing to filter down on say the last 10 this does not update other visuals in the report.
What can I do so that I am able to view the last 10 activities, but for the other visuals to update?
Rank = RANKX
(ALLEXCEPT(Sheet1,Sheet1[Name]),
CALCULATE(MAX(Sheet1[Date])),,
DESC)
It's likely you are applying that filter to only one visual.
It's better to implement the logic in the DAX calculation.
DAX Calculation
Rank =
VAR _Calc =
RANKX (
ALLEXCEPT ( Sheet1, Sheet1[Name] ),
CALCULATE ( MAX ( Sheet1[Date] ) ),
,
DESC
)
RETURN
IF ( _Calc <= 10, _Calc )

Power BI: Sum column distinct per another particular column

I am building a report about costumer complaints.
example
Now I am trying to get the right sum for "Reklamationskosten" (cost).
The correct answer is: 113 EUR.
The formula should do (in words):
"Sum the 'Reklamationskosten' for each 'Rekl. ID' but only once for each 'Reklamationskosten Art' "
Sure there is a way to do this in DAX but I cannot find out how.
Thank you all very much in advance!
For this you can create a measure using SUMX that iterates over a summarized table:
Reklamationskosten Measure =
SUMX (
SUMMARIZE (
'Table',
'Table'[Rekl. ID],
'Table'[Reklamationskosten Art],
'Table'[Reklamationskosten]
),
[Reklamationskosten]
)
This assumes that each "corresponding" row of Reklamationskosten Art has the same value of Reklamationskosten - else the values will be duplicated. You can alter the functionality of this by introducing aggregators handling multiple values using e.g. MAX:
Reklamationskosten Measure (Agg) =
SUMX (
SUMMARIZE (
'Table',
'Table'[Rekl. ID],
'Table'[Reklamationskosten Art],
"Reklamationskosten", MAX ( 'Table'[Reklamationskosten] )
),
[Reklamationskosten]
)

DAX - Get list from a filtered SUMMARIZE formula

So, I have the following tables in my Power BI :
Sales : Date | ID_Client | ID_Product | Amount
Client : ID_Client | Name_Client
I would like to get the number of unique BIG clients in any given month. I therefore use the following formula (which I then put in a column in a table with months in rows):
# BIG Clients =
VAR threshold = 10000
RETURN
(
CALCULATE(
DISTINCTCOUNT( Sales[ID_Client] ),
FILTER(
SUMMARIZE(
Sales,
Sales[ID_Client],
"Sales", SUM( Sales[Amount] )
),
[Sales] >= threshold
)
)
)
QUESTION IS : how can I get the list of those BIG clients for any given month? Let's say I click on the November number of big clients in my table, could another table nearby display the list of those clients ?
Thanks in advance for your kind help, I've been trying for a while :)
I assume that you have a table of clients with the Name column with a one to many relationship with the Sales table and that you do not have duplicate client names. Then you may create a [BIG Sales] measure to be used in a table or matrix visual with client names on the rows.
since [BIG Sales] evaluates to BLANK() for clients with less that threshold sales, they are automatically filtered out from the visual
BIG Sales =
VAR threshold = 10000
VAR BigCustomers =
FILTER(
ADDCOLUMNS(
VALUES( Clients[Name] ),
"Sales", SUM( Sales[Amount] )
),
[Sales] >= threshold
)
RETURN
SUMX(
BigCustomers,
[Sales]
)
You could create a table or matrix visual with the client on the rows and use your measure in the values field. This will show 1 for all big clients and return blank for the rest (which should hide them). If you don't want to show the measure, you can set the value is 1 in the filter pane and remove the measure from the values field.
A more direct option is to use a simple SalesAmount = SUM ( Sales[Amount] ) measure in the values field and filter like this

How can I get DAX to return just the record with a date closest to the slicer?

I'm hoping someone can help as I've completely run out of ideas.
I'm working on performance reporting data, producing a number of visuals to summarise the most recent data. To allow users to retrospectively produce reports from previous quarters, I have added a date slicer as a way to "View data as at xxxx date".
Here's a rough representation of my data table - the due dates are in English format (dd/mm/yyyy):
The ratings are calculated in another system (based on a set of targets), so there are no calculated columns here. In reality, there are a lot more measures that report on different time periods (some weekly, some annually, etc) and there are different lags before the data is "due".
I eventually managed to get a measure that returned the latest actual:
MostRecentActual =
VAR SlicerDate = MAX ( Dates[Day] )
RETURN
CALCULATE (
SUM ( Data[Actual] ),
Data[Data due] <= SlicerDate,
LASTDATE ( Data[Data due] )
)
I'm not completely sure I've done it right but it seems to work. I'd be happier if I understood it properly, so explanations or alternatives would be welcomed.
What I'm trying to do now is a basic summary pie chart at the beginning which shows the proportion of the measures that were red, amber, green or unrated as at the date selected. So I would need it to count the number of each rating, but only one for each measure and only for the date that is closest to (but before) the slicer date, which would vary depending on the measure. So using the above three measures, if the slicer was set to 10/10/2019 (English format - dd/mm/yyyy), it would count the RAGs for Q3 2019/20 for measures A an C and for Q2 2019/20 for measure B as there is a time lag which means the data isn't ready until the end of the month. Results:- A: Amber, B: Green, C:Red.
If I were able to create the measure that counted these RAGs, I would then want to add it to a pie chart, with a legend that is "Rating", so it would split the chart up appropriately. I currently can't seem to be able to do that without it counting all dates before the slicer (not just the most recent) or somehow missing ratings from the total for reasons I don't understand.
Any help would be very gratefully received.
Many thanks
Ben
Further update. I've been working on this for a while!
I have created a COUNTAX measure to try to do what I was wanting to do. In some circumstances, it works, but not all and not in the crucial ones. My measure is:
TestCountaxpt2 =
VAR SlicerDate = MAX ( Dates[Date] )
VAR MinDiff =
MINX (
FILTER (
ALL ( Data ),
Data[Ref] IN VALUES ( Data[Ref] ) &&
Data[Data due] <= SlicerDate
),
ABS ( SlicerDate - Data[Data due] )
)
VAR thisdate =
MINX (
FILTER (
ALL ( Data ),
Data[Ref] IN VALUES ( Data[Ref] ) &&
ABS ( SlicerDate - Data[Data due] ) = MinDiff
),
Data[Data due]
)
RETURN
COUNTAX (
FILTER ( Data, Data[Data due] = thisdate && Data[Ref] IN VALUES ( Data[Ref] ) ),
Data[RAG]
)
It produces the following table for a subset of the performance measures, which looks almost ok:
Table showing the result of the TestCountaxpt2 measure:
The third column is the measure above and it seems to be counting one RAG per measure and the dates look correct as the slicer is set to 3rd January 2020. The total for column 3 confuses me. I don't know what that is counting and I don't understand why it doesn't add up to 7.
If I add in the RAG column from the data table, it goes a bit more wrong:
Same table but with RAG Rating added:
The pie chart that is produced is also wrong. It should show 2 Green, 2 Red, 2 Grey (no rating) and 1 Amber. This is what happens.......
Pie chart for the DAX measure, with RAG Rating in the legend:
I can see what it is doing, which is to work out the most recent due date to the slicer in the whole table and using that (which is 1st Jan 2020) whereas I want it to calculate this separately for each measure.
Link to PBIX:
https://drive.google.com/file/d/1RTokOjAUADGHNXvZcnCCSS3Dskgc_4Cc/view?usp=sharing
Reworking the formula to count the ratings:
RAGCount =
VAR SlicerDate =
MAX ( Dates[Day] )
RETURN
COUNTAX (
ADDCOLUMNS (
SUMMARIZE (
FILTER ( Data, Data[Data due] <= SlicerDate ),
Data[Ref],
"LastDateDue", LASTDATE ( Data[Data due] )
),
"CountRAG", CALCULATE (
COUNTA ( Data[RAG] ),
Data[Data due] = EARLIER ( [LastDateDue] )
)
),
[CountRAG]
)
Here's the table it produces:
The reason for Total = 4 for the third column is straightforward. The SelectDate is maximal over all of the Refs in the table and there are only four Refs that match that date.
To fix this and get the totals you're after, you'll need to iterate over each Ref and calculate the SlicerDate for each independently and only then do your lookups or sums.
I haven't tested this code but it should give you an idea of a direction to try:
MostRecentActual =
VAR SlicerDate = MAX ( Dates[Day] )
RETURN
SUMX (
ADDCOLUMNS (
SUMMARIZE (
FILTER ( Data, Data[Data due] <= SlicerDate ),
Data[Ref],
"LastDateDue", LASTDATE ( Data[Data due] )
),
"SumActual", CALCULATE (
SUM ( Data[Actual] ),
Data[Data due] = EARLIER ( [LastDateDue] )
)
),
[SumActual]
)
Going inside to outside,
FILTER the table to ignore any dates beyond the SlicerDate.
Calculate the LastDateDue for each Ref using SUMMARIZE.
Sum the Actual column for each Ref value using its specific LastDateDue.
Iterate over this summary table to add up SumActual across all Refs in the current scope.
Note that for 4, only the Total row in your visual will contain multiple Refs since the innermost Data table inside FILTER is not the entire Data table but only the piece visible in the local filter context.

DAX TREATAS filtering by another table to get sales of all products on promotion

How to filter all products on promotion? Say we have two tables Sales and Budget without physical relationship. Here model is simplified and let's assume that it is the case, we cannot create physical relationship. We have to use virtual relationship.
We can see summary:
The two first columns are of the Sales table. The third column BudgetTreats is a measure:
BudgetTreatas =
CALCULATE (
SUM ( Budget[amount] ),
TREATAS (
VALUES ( Sales[id] ),
Budget[id]
)
)
Now I would like to resolve two things:
How to make a slicer to filter out only the products (id) which have BudgetTreatas?
How to create a measure for calculating sales but only for products which have a budget? So analogous measure as BudgetTreatas presented above.
And of course sample data: DAX TREATS.pbix
I posted an answer to my question but it is not to show an answer but rather to show working solutions, and give you idea on expected results. I would be grateful for any answer or comments.
References:
The Logic behind the Magic of DAX Cross Table Filtering
Virtual Filters Using TREATAS
How To Use The TREATAS Function - Power BI & DAX
Creating Virtual Relationships Using TREATAS - Advanced Power BI Technique
Measure calculating Sales filtered by ids in Budget table.
Surprisingly this is not working:
//not working:
SalesFilteredByBudget1 =
CALCULATE (
[Sales],
TREATAS ( VALUES ( Budget[id] ), Sales[id] )
)
It seems we need an extra table. If we add to the model a Bridge table with all sales id and connect it to Sales table on id (without connecting it to Budget table!) we may resolve the issue.
//works:
SalesFilteredByBudget2 =
CALCULATE (
[Sales],
TREATAS ( VALUES ( Budget[id] ), Bridge[id] )
)
So it seems filters propagate further from tables used in TREATAS( VALUES on the tables connected by physical relations.
If we want to make a measure without Bridge table we can make extra table as a table variable.
// works:
SalesFilteredByBudget3 =
VAR Lineage =
TREATAS ( VALUES ( Budget[id] ), Sales[id] )
VAR tbl =
CALCULATETABLE ( Sales, KEEPFILTERS ( Lineage ) )
VAR result =
CALCULATE ( SUMX ( tbl, [amount] ) )
RETURN
result