Using TREATAS to get Measure from Another Table - powerbi

I'm back with another issue. I have a sales table with transaction details on the products purchased. I also have a table with warehouse inventory information for each product. I'm trying to get the count of products purchased in a Table visualization with columns from the warehouse inventory table.
I tried both of the measures below, but they both return the total Count for each row rather than sliced by product. Any help would be greatly appreciated!
NumProductsfromSales1 = calculate([Count], treatas(values('Sales'[Product]), 'Inventory'[Product]))
NumProductsfromSales2 =
var lineage = treatas(values('Sales'[Product]), 'Inventory'[Product])
var tbl = calculatetable('Inventory Detail', KEEPFILTERS(lineage))
var result = calculate(sumx(tbl, [Count]))
return result

From this source, we see TREATAS works as follows.
[Filtered Measure] :=
CALCULATE (
<target_measure>,
TREATAS (
VALUES ( <lookup_granularity_column> ),
<target_granularity_column>
)
)
is equivalent to
[Filtered Measure] :=
CALCULATE (
<target_measure>,
INTERSECT (
ALL ( <target_granularity_column> ),
VALUES ( <lookup_granularity_column> )
)
)
The important part is the ALL function. That's why you're losing the filter context from the rows in the visual.
I'm not sure if this is the most efficient solution, but I think if you add Inventory as a filter table to your first attempt, it should maintain the filter context on that table from the row in the visual.
NumProductsfromSales1 =
CALCULATE (
[Count],
'Inventory',
TREATAS ( VALUES ( 'Sales'[Product] ), 'Inventory'[Product] )
)
Edit: Regarding your comment, try the following:
a =
VAR top5prod =
SELECTCOLUMNS (
TOPN (
5,
SUMMARIZE ( Sales, Sales[Product], "Count", [Product Count] ),
[Count]
),
"Product", Sales[Product]
)
RETURN
CALCULATE (
[Product Count],
FILTER ( 'Inventory', 'Inventory'[Product] IN top5prod )
)
Using FILTER isn't as efficient as TREATAS but see if it works.
It's very difficult to answer this sort of question without having anything reproducible to work with.

Related

Count the number of occurrences after associated date of certain value in Power BI

I'm conducting an exercise around examining test results after tutoring has occurred. Essentially looking at the rates of "pass" post tutoring within the context of a given student. Where the ultimate outcome would be:
pass rate after tutoring = [count passes]/[count test date] WHERE test date > tutoring date.
For example:
Ideally, the final output of the measure would be = 1 (1/1)
Would anyone be able to point me in the direction of achieving this through a Power BI measure?
I've attempted the following to get the single oc with no luck:
Measure 3 = CALCULATE(COUNT(Table[Test Pass?]),FILTER(Table,Table[Test Date]>CALCULATE(Min(Table[Tutoring Date]),FILTER(Table,Table[Tutor (?)] <> BLANK ))))
Where I would then use the student column in a matrix with the measure to group pass rates post tutoring by student
I have used this simple flat table data model:
You can calculate this with a measure that needs to be evaluated with your Student column:
Pass Rate After Tutoring =
VAR _tutor_date =
CALCULATE (
MAX ( 'Table'[Tutoring Date] ),
ALLEXCEPT ( 'Table', 'Table'[Student] )
)
VAR _tests_post_tutor =
CALCULATE (
COUNTROWS ( 'Table' ),
ALLEXCEPT ( 'Table', 'Table'[Student] ),
'Table'[Test Date] > _tutor_date
)
VAR _successes =
CALCULATE (
COUNTROWS ( 'Table' ),
ALLEXCEPT ( 'Table', 'Table'[Student] ),
'Table'[Test Date] > _tutor_date,
'Table'[Test Pass]
)
RETURN
DIVIDE ( _successes, _tests_post_tutor )
But this assumes that students are only tutored for one specific test, and are tutored once.

Conditional Filtering on Report Data in Power BI

I have a table entry for multiple Product and Many different features. All the data has date time in shown format.
As we can see that all products has entries across different time. My aim is to filter the details related to the product by latest time of everyday.
I was able to split the Time col in Date col & Time col separately.
You can achieve that by creating a new table in Dax for eg. (because I don't know what do you want to do with rows with the same timestamp I show both rows for C)
YourFilteredTable =
VAR __trt =
TREATAS (
SELECTCOLUMNS (
ADDCOLUMNS (
SUMMARIZE (
ADDCOLUMNS (
ALL ( YourTable[Product], YourTable[Time] ),
"day", DATEVALUE ( YourTable[Time] )
),
YourTable[Product],
[day]
),
"MaxDate", CALCULATE ( MAX ( YourTable[Time] ) )
),
"Prod", [Product],
"MaxDate", [MaxDate]
),
YourTable[Product],
YourTable[Time]
)
RETURN
SUMMARIZECOLUMNS (
YourTable[Product],
YourTable[Quant],
YourTable[Time],
__trt
)

Filtering on calculated column of Cartesian product in DAX

I need a slicer for ticking only those Products and Regions which have budgeted Targets.
My data model is a bit complicated than I show here. In my real scenario table Budget does not exist and Target values have to be calculated from other tables of varying granularity. Lets assume we cannot use calculated column on Budget table.
Here green tables are one-column-all-values-dimension bridges. The red table is a Cartesian product of Products and Brands with calculated Target.
Here is a DAX code for the red table I cooked to solve the problem.
#Brand x Region =
ADDCOLUMNS (
CROSSJOIN ( '#product', '#region' ),
"Target", CALCULATE ( SUM ( Budget[target] ) ),
"IsTarget", IF ( CALCULATE ( SUM ( Budget[target] ) ) > 0, "Yes", "No" )
)
The table shows like this:
But such cunningly obtained column IsTarget does not affect my visuals through the slicer. How to fix it.
File PBIX here.
Edit after comments.
Alexis, is that what you mean? I added column P#R which is concatenation of Product and Region. It seems to work:-)
This is what I was suggesting, where the bottom relationships are on the Index columns.
In order to do this, my #Brand x Region table was this:
#Brand x Region =
VAR CrossProduct =
ADDCOLUMNS (
CROSSJOIN ( '#product', '#region' ),
"Target",
CALCULATE (
SUM ( Budget[target] ),
FILTER (
Budget,
Budget[product] = EARLIER ( '#product'[product] ) &&
Budget[region] = EARLIER ( '#region'[region] )
)
)
)
RETURN
ADDCOLUMNS(
CrossProduct,
"IsTarget", IF ( [Target] > 0, "Yes", "No" ),
"Index", RANKX(CrossProduct, '#product'[product] & '#region'[region])
)
(Note: The filtering has to be explicit since I'm not using the relationships you originally had.)
From there I pulled over the index to the FactTableSales and Budget with a lookup:
Index =
LOOKUPVALUE (
'#Brand x Region'[Index],
'#Brand x Region'[product], [product],
'#Brand x Region'[region], [region]
)
Note that creating an index column is often easier in the query editor rather than trying to do it in DAX but you can't modify a calculated table in the query editor.

Using summarize and userelationship to generate a sum based on a condition

Story:
I have two date columns in my fact table, one is for orderdate and the second is for orderdate/refund/cancelled date.
I created two relationships between the date table and the fact table.
Active: Date > OrderDate
Inactive: Date > OtherDate
I would like to sum the # of refunds per day using the inactive relationship.
What I tried:
Returns =
VAR summary =
SUMMARIZE (
FILTER ( Query1, Query1[kind] = "refund" ),
Query1[orderId],
"returns", MAX ( Query1[amount] )
)
RETURN
CALCULATE (
MAX ( Query1[amount] ),
USERELATIONSHIP ( Query1[OtherDate], DateTable[Date] ),
summary
)
For some reason, it's using the active date column. Any suggestion on how to fix the above formula?
I'm not sure I understand how you are intending to use the summary variable here, but note that USERELATIONSHIP doesn't affect it at all since it's already computed.
You might not need that variable at all. Try this:
Returns =
CALCULATE (
MAX ( Query1[amount] ),
USERELATIONSHIP ( Query1[OtherDate], DateTable[Date] ),
Query1[kind] = "refund"
)

DAX measure not working when RLS is turned on - Join paths are expected to form a tree

In Power BI, I have the following error for a measure when RLS is turned on (this error does not show when RLS is off):
Join paths are expected to form a tree but the table has two join paths
These are the relevant relationships in the model:
I have an inactive relationship. This inactive relationship is used in the measure with the problem. But as it is inactive, I would have thought it wouldnt be an issue?? The measure is:
TTipsInvs =
VAR SalesValue =
CALCULATE (
SUM ( ANSAPBICustomerTransDetailed[Outstanding] ),
USERELATIONSHIP ( 'ANSAPBICustomerTransDetailed'[SiteID], ANSAPBISites[Site ID] )
)
RETURN
IF ( ISBLANK ( SalesValue ), 0, ( SalesValue ) )
Any way to avoid this issue when RLS is turned on?
Cheers for all help
TTipsInvs =
VAR SiteID =
CALCULATETABLE (
VALUES ( ANSAPBISites[Site ID] ) )
VAR SalesValue =
CALCULATE (
SUM ( ANSAPBICustomerTransDetailed[Outstanding] ),
TREATAS ( SiteID, 'ANSAPBICustomerTransDetailed'[SiteID] ) )
RETURN
IF ( ISBLANK ( SalesValue ), 0, ( SalesValue ) )
I'd like to add to #user9824134's answer that unfortunately did not have much of an explanation (cannot edit).
Why TREATAS:
The docs explain that this function applies the result of the first argument (clientID) on the column in the second argument ('ANSAPBICustomerTransDetailed'[SiteID])
Why this works:
Not too sure how RLS enforces the joint path, but the "always-on" idea explained by #asp8811 makes sense to me.
The TREATAS is essentially working as an alternative to CROSSFILTER in this case. By applying the filter of clientID on the SiteID column of the ANSAPBICustomerTransDetailed table, it is emulating CROSSFILTER.
I'd have to test efficiency, but I suspect performance should be similar as VALUES already only returns a distinct list.
The below approach also works and is much shorter. The CALCULATETABLE expression does nothing if a filter is not passed to it, so simply using VALUES is enough.
TTipsInvs =
VAR clientID = VALUES ( ANSAPBISites[Site ID] )
VAR SalesValue =
CALCULATE (
SUM ( ANSAPBICustomerTransDetailed[Outstanding] ),
TREATAS ( clientID, 'ANSAPBICustomerTransDetailed'[SiteID] ) )
RETURN
IF ( ISBLANK ( SalesValue ), 0, ( SalesValue ) )
Did a quick test:
And this looks to work without the need of enabling or disabling relationships.
Before RLS:
After RLS: