Dax All function inside AverageX function - powerbi

Can anyone explain me what does ALL function do below inside function. Does it make relationship between 'Sales' table with 'Product' table?
_Sales by Product Column Chart Colour =
var avgSales = AVERAGEX(
ALL('Product'[Product])
, [Sales Amount]
)
return
IF([Sales Amount] < avgSales, "Dark Blue")

OK. ALL is a versatile DAX function. It can be used either as a table function or calculate modifier.
Let's analyze the behavior of ALL, first checking your code:
1))
As a Table Function like in your code
Sales by Product Column Chart Colour =
var avgSales = AVERAGEX(
ALL('Product'[Product])
,[Sales Amount]
)
RETURN
IF([Sales Amount] < avgSales, "Dark Blue")
It returns all the unique values of [Product] column on Product table, and for each row, evaluate sales amount measure. It ignores the filter on product column and calculates overall averages of all products. You know the rest starting with if.
2))
As a calculate modifier like in below measure:
Test_Measure =
CALCULATE(
SUM(Sales[Amount]),
ALL(Product)
)
It removes all the filters on all the columns of the product table, and affects the filter context directly.
To summarize, It is important where you use ALL. Depending on it, It reacts differently.
I hope this is enough for you to understand its behavior.

Related

DAX DEFINE returns column not found error

This works:
EVALUATE
ADDCOLUMNS(
FILTER (Sales, [StoreKey] = 155 ) ,
"Margin", (Sales[SalesAmount] - Sales[TotalCost])
)
However, if I try to define a function, I get an error:
DEFINE VAR Margin = Sales[SalesAmount] - Sales[TotalCost]
EVALUATE
ADDCOLUMNS(
FILTER (Sales, [StoreKey] = 155) ,
"Margin", Margin
)
Query (1, 21) A single value for column 'SalesAmount' in table 'Sales'
cannot be determined. This can happen when a measure formula refers to
a column that contains many values without specifying an aggregation
such as min, max, count, or sum to get a single result.
What is this error and how to fix it?
There are 2 problems with the second code:
It's missing Row Context
VAR is not a function, it's a variable. Functions in DAX are Measures
What is "Row Context"? In short, in Power BI data is stored in a database. When you are referring to a column in the database, you must either: aggregate the data in it (i.e., sum it), or provide a specific row ("row context").
In your first code, function ADDCOLUMNS is an iterator. It means that it loops a table row by row, and for each record does a calculation. Since during each iteration it "knows" which row it's on, you can refer to the table fields without problems.
In the second code, this line:
Margin = Sales[SalesAmount] - Sales[TotalCost]
has no row context - it does not know which record to use for the calculation, and hence the error. You must either aggregate the data first, or put this calculation inside an iterator.
In this particular case, the simplest solution is to use aggregation:
DEFINE
MEASURE 'Sales'Margin = SUM ( Sales[SalesAmount] ) - SUM ( Sales[TotalCost] )
EVALUATE
ADDCOLUMNS (
CALCULATETABLE ( Sales, Sales[StoreKey] = 155 ),
"Margin", [Margin]
)
Here, we first aggregate amounts and costs and calculate margin. Then, inside of ADDCOLUMNS we iterate table Sales filtered for a specific store, and for each row we call the measure defined above.
If you need to use an iterator instead of aggregation, you can do something like this:
DEFINE
MEASURE 'Sales'Margin = SUMX(Sales, Sales[SalesAmount] - Sales[TotalCost] )
EVALUATE
ADDCOLUMNS (
CALCULATETABLE ( Sales, Sales[StoreKey] = 155 ),
"Margin", [Margin]
)

DAX SUMMARIZE miss applied slicers

I have a slicer, called COUNTRY and applied to table MY_TABLE. When I calculate a measure, everything works as expected:
-- calculates distinct count only for COUNTRY = x
Some Measure = DISTINCTCOUNT('MY_TABLE'[SOME_COLUMN])
The problem is SUMMARIZE ignores slicer selection:
-- calculates distinct count accross all countries: x, y, z, etc.
Calculated Table =
RETURN SUMMARIZE(
'SOME_TABLE',
[CATEGORY],
"COUNT", DISTINCTCOUNT('SOME_TABLE'[SOME_COLUMN])
)
How to make SUMMARIZE take into account slicers?
Only Measures are "responsive", calculated tables and columns get calculated and created once, when the data are loaded.
Note that if a calculated table is used inside a measure it will behave correctly, but as you may know, a measure must return a scalar value and not a table. (ie you can use summarize inside a measure, you can then filter the obtained table and return the sum of one column)
Of course, you can filter calculated table with a slicer. If you can, go for SUMMARIZECOLUMNS because this function is better optimized then SUMMARIZE, and has arguments for filtering.
Filtering SUMMARIZECOLUMNS
If you want to stick to SUMMARIZE, you can filter your table by wrapping it with CALCULATETABLE.
Calculated Table =
CALCULATETABLE (
SUMMARIZE (
'SOME_TABLE',
[CATEGORY],
"COUNT", DISTINCTCOUNT ( 'SOME_TABLE'[SOME_COLUMN] )
),
Dim[Color]
= SELECTEDVALUE ( Slicer[SlicerValues] )
)
Should FILTER be used inside or outside of SUMMARIZE?

Running total based on other columns value

I need to calculate running total of forecast amount starting from maximum value, based on two stock locations and once for each product (product numbers are repetitive due to stock locations). e.g product no "1" should be used once for running total.
My first code, which didn't sum the same forecast amounts independently based on item no.
RunningTotal1 =
VAR
CurrentAmount= Listing[Forecast Amount]
RETURN
SUMX (
FILTER (
Listing;
Listing[Forecast Amount]>= CurrentAmount);
Listing[Forecast Amount])
My second code where running total was based on stock location, it calculates for each location independently still didn't sum the same forecast amounts independently based on item no.
RunningTotal2 =
VAR CurrentAmount = Listing[Forecast Amount]
VAR Location = Listing[Stock Location]
RETURN
SUMX (
FILTER (
Listing;
Listing[Stock Location] = Location &&
Listing[Forecast Amount]>= CurrentAmount);
Listing[Forecast Amount])
But when I add second location to my formula it gives an error.
"DAX comparison operations do not support comparing values of type Text with values of type True/False. Consider using the VALUE or FORMAT function to convert one of the values."
RunningTotal3 =
VAR CurrentAmount = Listing[Forecast Amount]
VAR LocationW = Listing[Stock Location] = "Warehouse"
VAR LocationT = Listing[Stock Location] = "Total Stock"
RETURN
SUMX (
FILTER (
Listing;
Listing[Stock Location] = LocationW ||
Listing[Stock Location] = LocationT &&
Listing[Forecast Amount]>= CurrentAmount);
Listing[Forecast Amount])
What I expect is
Hello #RADO,
I tried to add as measure but couldn't succeed therefore I added as a new column. I realize my code is wrong, in your image item no 5 and 6 have different number. my formula is
Forecast Index = RANKX(Listing;Listing[Forecast Amount])
here's the result Forecast Index
regards
You need to add a column to your "Listing" table that defines order for the running total. You can't use Forecast Amount for that, because there are cases where different items have the same amounts (for example, items 66 and 99), and there is no way to resolve these ties (which items should be accumulated first - 66 or 99? No way to tell).
Often, date/time fields are used for that, but if you don't have them, you can add an index based on whatever rules you need. For this example, I manually added "Forecast Index" as follows:
Forecast index here is simply a sorting order - if you sort by it, you will get the layout exactly matching your "desired result" table.
Then, create a measure:
RT Expected =
VAR Current_Index = MAX ( Listing[Forecast Index] )
VAR Summary_Table =
SUMMARIZE (
FILTER (
ALL ( Listing ),
Listing[Forecast Index] <= Current_Index &&
Listing[Stock Location] <> "Without Stock" ),
Listing[Item No],
Listing[Forecast Amount] )
RETURN
SUMX ( Summary_Table, Listing[Forecast Amount] )
Result:
Note: If you don't want to see Items 2 and 4, simply remove them from the visual filter.
How it works:
First, we use FILTER to create a virtual table that a) ignores "Without Stock" locations, and b) keeps only forecast amounts that we need for the running total;
Second, we use SUMMARIZE to group that virtual table by Item No and Forecast Amount. The grouping eliminates duplicates;
Finally, we use SUMX to iterate the de-duplicated table, and sum up all relevant amounts.
Edit:
You can create a proper index using PowerQuery:
In your left panal, Go to "Data", and select "Listing" table;
Right-click the table, and select "Edit Query". Power BI will take you to the Power Query window;
In Power Query, first, sort column "Forecast Amount" Descending. Then, sort column "Item No" Ascending. This will arrange your records in the same order as you have them in your picture;
Finally, in Power Query window, go to "Add Column", then "Index Column", select "From 1". Power Query will create an index column for you, and name it "Index". You can rename it as needed (i.e, to "Forecast Index");
Click "Close and Apply", and then build the measure I suggested using this new index column as an input.
In case these instructions are not clear, refer to this article:
https://www.excelguru.ca/blog/2018/06/14/ranking-method-choices-in-power-query/

Including groups with no values in stacked column chart

I'm building a chart that will cumulatively sum Invoice Values for the next month, broken out by category of sale. It looks like this:
My problem is that for particular slicer values, there might not be any invoices for a particular category, and thus the groups just don't show in the graph:
This looks scrappy, so I'm trying to force them to show. Given the rows simply don't exist the way I'm trying to do this is to have a new table which has a row per-date-per-category, and use a measure to cumulatively sum all the data from my source table. So for example given this source table:
I've built the structure of this table, but I need to find a way to add the "Cumulative Value" field that's also shown:
Unfortunately I can't work out how to make that work. The usual cumulative sum syntax would be:
Cumulative Value = (
CALCULATE(
SUM('Table 1'[Value]),
FILTER(ALLSELECTED('Table 1'), ISONORAFTER('Table 1'[Date], MAX('Table 1'[Date]), DESC))
)
)
And I can't seem to add in another filter expression without either
Breaking it such that it returns different values per category but the same value for every date
Breaking it such that it returns different values per date but the same value for each category
So; what Measure can I build to create that "Cumulative Value" field?
Never mind, I got it. Full DAX for the answer was:
CumulativeValue =
VAR CurrActionDate = MAX('Table 2'[Date])
VAR CurrTransType = MAX('Table 2'[Category])
RETURN (
CALCULATE(
SUM('Table 1'[Value],
FILTER(
ALLSELECTED('Table 1'),
'Table 1'[Date] <= CurrActionDate
),
FILTER(
ALLSELECTED('Table 1'),
'Table 1'[Category] = CurrTransType
)
)
)
Ta-da! Cumulative sum across different groups with no blank values.

Power BI Rank within Matrix Visual

I've spent many weeks trying to get this to work including a posting at another site. No luck. Not sure what I'm missing.
The following code gets me the table of data that I need. However, I want just the "rank" value and I want it for each row within a matrix visual.
First some background, the PowerBI page has slicers on dates and "base" product. Any given product may be sold in multiple countries. All carry the same base product suffix with a country-specific prefix.
The matrix in question displays several aspects of all the product variants for the selected base product. I want to show where each variant ranks (unit sales) within its country.
VAR tblCountrySales =
SUMMARIZE (
FILTER(
tblSalesUnits,
RELATED(tblProducts[Country])="US"
),
tblProducts[ProdID],
"Total Sales", SUM ( tblSalesUnits[Units] )
)
RETURN
ADDCOLUMNS (
tblCountrySales,
"ProductRank", RANKX ( tblCountrySales, [Total Sales] )
)
Is there a way to either pull just the rank for a single product from the above code, or, better yet, a DAX pattern that will get me the rank by unit sales of each product variant within its respective country?
I've use these statements to successfully get the product ID and country for each row within the visual.
VAR ProdSales = SUM(tblSales[Units])
VAR ProdCountry = SELECTEDVALUE(tblProducts[Country])
Any help is greatly appreciated. I assume I'm missing something with row context within the visual as a simple COUNTROWS on the table expressions above always returns "1". Being new to PowerBI and DAX I'm still trying to grasp the nuances of filter and row contexts.
The products table contains data like...
ProdID.....BaseID....Name...Country
7190...........7190.....xxxx.....US
150207190......7190.....XXXX....Panama
241807190......7190.....xxxx.....Spain
The sales table contains data like...
ProdID......SalesMonth......Units.....USD
7190........July 2010.......4563....$23491.00
150207190...July 2010.......2543....$16235.00
241807190...July 2010.......1263....$8125.00
There is a dates table as well that links the SalesMonth to the usual selection of date display formats. The two tables above are linked via ProdID, though the visuals are sliced by the BaseID. I'd attach a picture, but don't have permissions to do so.
With some more tinkering I found this solution.
Country Rank =
VAR ProdSales = SUM(tblSales[Units])
VAR ProdCountry = SELECTEDVALUE(tblProducts[Country])
VAR tblCountrySales =
SUMMARIZE (
FILTER(
ALLEXCEPT(tblProducts,tblProducts[BaseID]),
tblProducts[Country]=ProdCountry
),
tblProducts[ProdID],
"Total Sales", SUM ( tblSales[Units] )
)
RETURN
IF(ProdSales>0,COUNTROWS(FILTER(tblCountrySales,[Total Sales]>ProdSales))+1,BLANK())