This is follow up question of the one asked here. However this time two columns have different granularity and are located in different tables. So simple SUMX solution proposed earlier is not applicable. I attach SumDifferntGranularity.pbix file.
How to construct a DAX measure which returns sum of either BudgetProduct (if possible) or BudgetBrand. The logic is take Brand if Product is empty. So expected results looks like this:
+---------+-------------+---------------+-----------------+
| Manager | BudgetBrand | BudgetProduct | Expected result |
+---------+-------------+---------------+-----------------+
| Alice | 16 | 15 | 15 |
| John | 7 | | 7 |
| Martha | 21 | 21 | 21 |
| Zadar | 11 | | 11 |
+---------+-------------+---------------+-----------------+
| Total | 55 | 36 | 54 |
+---------+-------------+---------------+-----------------+
In this example, all Managers have budget defined on Brand, but some Managers (Alice and Martha) have budget defined on Products. How to construct a measure which will take budget defined on products, if possible, but if not possible then it will take the budget defined on Brands.
I think this will work:
Expected Result =
VAR Summary =
SUMMARIZE (
Unique_Manager,
Unique_Manager[Manager],
"Budget_Brand", SUM ( Budget_Brand[BudgetBrand] ),
"Budget_Product", SUM ( Budget_Product[BudgetProduct] )
)
RETURN
SUMX (
Summary,
IF ( ISBLANK ( [Budget_Product] ), [Budget_Brand], [Budget_Product] )
)
This groups by Manager and calculates a summary table with the sum for BudgetBrand and BudgetProduct for each and the iterates through this summary table with SUMX using the logic specified.
Here's a bit cleaner implementation
Expected Result =
SUMX (
VALUES ( Unique_Manager[Manager] ),
VAR SumBrand = CALCULATE ( SUM ( Budget_Brand[BudgetBrand] ) )
VAR SumProduct = CALCULATE ( SUM ( Budget_Product[BudgetProduct] ) )
RETURN
IF ( ISBLANK ( SumProduct ), SumBrand, SumProduct )
)
I this one, we don't need a calculated table to iterate over. Instead, we iterated over all the distinct values of Manager in the local filter context and sum BudgetBrand and BudgetProduct within that context. Note that I've wrapped the sums in CALCULATE. This is done to perform the context transition from the row context inside SUMX (the particular Manager) to having that Manager as a filter context on BudgetBrand and BudgetProduct. Storing these sums as variables makes for a more readable IF line and only requres SumProduct to be computed once instead of twice.
Related
I'm trying to calculate the daydiff between when the first (H1) and the second (H2) product have been bought for each customer (ID)
I can do it if the dates are on the same line, but not on mulitple rows. There are 5.6mil rows in all with 30 different products, but right now its only between H1 and H2
The result i'm after is something like
For a data source with 5.6M rows, I would only recommend doing it though native server-side query unless the calculations are not required to evaluate in respect to some filter context. Else, you can do it through the following DAX measure.
If you have a table like this and you want the DateDIff by ID for each preceding PurchaseDate
| ID | Product | PurchaseDate |
|----|---------|--------------|
| 10 | H1 | 2021-09-15 |
| 10 | H2 | 2021-09-19 |
| 20 | H1 | 2021-05-01 |
| 20 | H2 | 2021-06-05 |
| 20 | H3 | 2021-07-08 |
you can write the following measure
Measure =
VAR _curentlyVisibleDateById =
MAX ( 'fact'[PurchaseDate] )
VAR _immediatelyPrecedingDateById =
CALCULATE (
CALCULATE (
MAX ( 'fact'[PurchaseDate] ),
'fact'[PurchaseDate] < _curentlyVisibleDateById
),
ALLEXCEPT ( 'fact', 'fact'[ID] )
)
VAR _diffbyId =
DATEDIFF ( _immediatelyPrecedingDateById, _curentlyVisibleDateById, DAY )
RETURN
_diffbyId
Edit
If you want to limit calculations to only specific groups of Product; i.e. only for Products H1,H2,H3 then please use this
Measure =
VAR _curentlyVisibleDateById =
CALCULATE (
MAX ( 'fact'[PurchaseDate] ),
'fact'[Product] IN { "H1", "H2", "H3" }
)
VAR _immediatelyPrecedingDateById =
CALCULATE (
CALCULATE (
MAX ( 'fact'[PurchaseDate] ),
'fact'[PurchaseDate] < _curentlyVisibleDateById
),
ALLEXCEPT ( 'fact', 'fact'[ID] ),
'fact'[Product] IN { "H1", "H2", "H3" }
)
VAR _diffbyId =
DATEDIFF ( _immediatelyPrecedingDateById, _curentlyVisibleDateById, DAY )
RETURN
_diffbyId
I have a Power BI report and I want to find the last date some action took place that had a non-0 value. In the following example:
|-------------|------------|
| ActionDate | ActionAmt|
|-------------|------------|
| 1-Feb | -100 |
|-------------|------------|
| 1-Feb | 100 |
|-------------|------------|
| 10-Jan | 150 |
|-------------|------------|
I want to return the 10-Jan date, not 1-Feb, since 10-Jan is the first non-0 value summed by ActionDay. My code returns 1-Feb:
Last Action Date =
VAR maxdatekey =
CALCULATE ( MAX ( 'Action'[ActionDateKey] ), 'Action'[ActionAmount] > 0 )
RETURN
IF (
maxdatekey,
FORMAT (
LOOKUPVALUE ( 'Date'[DateValue], 'Date'[DateKey], maxdatekey ),
"dd-MMM-yyyy"
)
)
How do I further group this to exclude the summarized 0 days?
I think you're looking for something like this where you summarize by date when calculating the amount:
LastActionDate =
VAR Summary =
SUMMARIZE (
'Date',
'Date'[DateValue],
"Amt", CALCULATE ( SUM ( 'Action'[ActionAmount] ) )
)
RETURN
FORMAT (
MAXX ( FILTER ( Summary, [Amt] > 0 ), 'Date'[DateValue] ),
"dd-MM-yyyy"
)
I have a transactional table that looks like data that would flow in from a point of sale. Using DAX/Power BI, I want to be able to count and sum the instances where Item A is more frequent on the invoice than Item B.
I'm having a hard time pasting my data but imagine a transactional dataset with 3 Columns: Invoice Number, Qty sold, Product
Invoice | Qty sold | Product
---------------------------------
1111 | 5 | Apples
1111 | 6 | Bananas
1111 | 6 | Oranges
1112 | 10 | Apples
1112 | 5 | Bananas
1112 | 3 | Oranges
1112 | 3 | Strawberries
And I want to be able to see it every combination of products above and how frequently 1 has a greater sales quantity than the other:
Apples > Apples: 0
Apples > Bananas: 1
Apples > Oranges: 2
Apples > Strawberries: 1
Bananas > Bananas: 0
Bananas > Apples: 1
Bananas > Oranges: 2
etc
I have tried duplicating the table and doing a many to many join on invoice. From there, count rows from table 1 where count > than table 2 using the "related" and "related table" functions (this is how I would do it in SQL). This hasn't worked due to the many to many nature. I have also tried something like this but it is not providing the desired output:
MoreFreq =
CALCULATE(
COUNT(Fact2[Qty Sold]),
FILTER(
Fact2,
Fact2[Qty Sold] > Fact1[Qty Sold]
)
)
Any help would be appreciated. Thanks!
Since you only provided a single table, not really sure how you plan to display it visually, with more Dimensions to provide selection you will be able to do something more flexible.
You could create a Calculated Table:
Table =
ADDCOLUMNS(
DISTINCT(GENERATE(VALUES(Fact2[Product]);SELECTCOLUMNS(VALUES(Fact2[Product]);"Product2";[Product])));
"Count";
COUNTX(VALUES(Fact2[Invoice]);
VAR p1 = [Product]
VAR p2 = [Product2]
VAR p1c = CALCULATE(SUM(Fact2[Qty]);p1=Fact2[Product])
VAR p2c = CALCULATE(SUM(Fact2[Qty]);p2=Fact2[Product])
RETURN
IF(p1c>0 && p2c>0 && p1c>p2c;1)
)
)
I took a crack at it, most of the complexity stems from the fact that you want to add the product combination (e.g. "Apples > Bananas") to visual in Power BI. In order to do this it needs to be a physical column in your data model. That eliminates create a single measure. I chose to use a calculated table. In this table I calculate all the product combinations and their related quantity per invoice and add a new display column "product combination":
Crossjoin =
FILTER (
ADDCOLUMNS (
CROSSJOIN (
'Table',
SELECTCOLUMNS ( VALUES('Table'[Product]), "ProductName", 'Table'[Product] )
),
"RelatedQty", CALCULATE (
SUM ( 'Table'[Qty sold] ),
FILTER (
ALLEXCEPT ( 'Table', 'Table'[Invoice] ),
'Table'[Product] = EARLIER ( [ProductName] )
)
),
"Product Combination", 'Table'[Product] & " > " & [ProductName]
),
'Table'[Product] <> [ProductName]
&& [RelatedQty] > 0
)
After that the measure to calculate the instances where a product is sold more than another is pretty straightforward:
Measure =
SUMX (
'Crossjoin',
IF ( 'Crossjoin'[Qty sold] > 'Crossjoin'[RelatedQty], 1, 0 )
)
An alternative solution could be to generate all the "Product Combinations" possible from the data at Data Load as a new table and do the crossjoin inside the measure. I chose the calculated table to make the calculations more visible.
Hope that helps!
Jan
You can do this with two copies of a product dimension, and no relationships to the fact table.
'Fact' is as you shared in your original post.
'Dim1' and 'Dim2' are each a distinct list of all products.
Expected usage is that you put 'Dim1'[Product1] and 'Dim2'[Product2] onto a table or matrix visual. For matrix, you could do one on rows and one on columns.
// base measure
Quantity = SUM ( 'Fact'[Qty Sold] )
// the measure you want
Dim1 > Dim2 =
// Count the rows defined by the FILTER table expression.
// This will be a count of distinct invoices, based on a
// filter predicate.
COUNTROWS (
// Iterate invoices, keeping only those that have Dim1 > Dim2
FILTER (
VALUES ( 'Fact'[Invoice] ),
// Fore each invoice, calculate Dim1Qty and Dim2Qty
VAR Dim1Qty =
CALCULATE (
[Quantity],
TREATAS ( VALUES ( 'Dim1'[Product1] ), 'Fact'[Product] )
)
VAR Dim2Qty =
CALCULATE (
[Quantity],
TREATAS ( VALUES ( 'Dim2'[Product2] ), 'Fact'[Product] )
)
RETURN
// Keep only invoices where this predicate is true
Dim1Qty > Dim2Qty
)
)
I have a closing date and delivery date column, if the date difference greater than 1 then, I need to generate date series with a closing date column. I have attached the example closing date and delivery date details below.
I want the output to be like the below one
Please help me in solving this issue.
Using this extended table and the following code I believe you would get the desired results:
Closing | Delivery | Difference | Order
---------------------------------------
190228 | 190321 | 21 | A
190228 | 190301 | 1 | B
190310 | 190317 | 7 | C
ExpandedDeliveryTable =
SELECTCOLUMNS(
FILTER(
ADDCOLUMNS(
CROSSJOIN(
CALCULATETABLE(
'Deliveries';
'Deliveries'[Difference] > 1
);
GENERATESERIES(
0;
MAX('Deliveries'[Difference]);
1
)
);
"Filter";
IF( [Delivery]-[Closing] < [Value]; 1; BLANK() )
);
[Filter] <> 1
);
"Closing_Date"; [Closing]+[Value];
"DeliveryDate"; [Delivery];
"Date Diff"; [Value];
"Order"; [Order]
)
This generates a new table looking like this:
]
I am trying to create a simple measure that represents a countries sales as a percentage of total sales. I first created a Slicer on the page so the user can filter to a specific country. I then wanted to use the sales of the filtered country as the numerator, and for the denominator using the ALL function remove all filters so it sums the grand total. The idea is I would then represent the data for each store (rows) to see how that store performs
However, when I do this all I see is 100% for every row when I run the report.
How can I make sure the numerator and denominator correctly understand the context / filters when doing their calculation.
Test Performance Variance =
VAR __BASELINE_VALUE = SUM('Test'[Sales])
VAR __VALUE_TO_COMPARE = SUM('Test'[Sales])
RETURN
IF(
NOT ISBLANK(__VALUE_TO_COMPARE),
DIVIDE(__VALUE_TO_COMPARE,
CALCULATE( __BASELINE_VALUE,ALL(Test[Country])))
)
Desired result is this:
Store | Sales | Performance
ABC | 15 | 15%
DEF | 65 | 65%
GHI | 20 | 20%
But instead I am seeing:
Store | Sales | Performance
ABC | 15 | 100%
DEF | 65 | 100%
GHI | 20 | 100%
You are putting a constant (the VAR you defined) within a CALCULATE, so the ALL doesn't do anything because a constant is fixed and doesn't change with the filter context.
Try rewriting the measure like this:
Test Performance Variance =
VAR __BASELINE_VALUE = CALCULATE ( SUM ( 'Test'[Sales] ), ALL ( Test[Country] ) )
VAR __VALUE_TO_COMPARE = SUM ( 'Test'[Sales] )
RETURN
IF (
NOT ISBLANK ( __VALUE_TO_COMPARE ),
DIVIDE ( __VALUE_TO_COMPARE, __BASELINE_VALUE )
)