I've got my data structured as below in a contractProducts table, gives each combination of contract and product as well as the previous product for each contract (each contract can have more than one product).
contract_id | product_id | previous_product_id |
---|---|---|
1 | 1 | 1 |
2 | 2 | 1 |
2 | 3 | 3 |
3 | 3 | 2 |
4 | 1 | 3 |
5 | 3 | 1 |
6 | 2 | 3 |
6 | 1 | 2 |
7 | 3 | 3 |
8 | 1 | 1 |
9 | 1 | 2 |
9 | 2 | 3 |
10 | 3 | 1 |
I've also got a product benefits table (below), showing all the benefits selected for each product.
product_id | benefit_name |
---|---|
1 | legs |
1 | arms |
1 | head |
1 | back |
2 | legs |
2 | arms |
2 | hands |
2 | feet |
3 | legs |
3 | hands |
3 | eyes |
3 | left kidney |
These have a many-many relationship between them based on the product id on each, I'd love to be able to refactor it or somehow split it all out to a much more sensible model, but due to the system I'm working with and how the benefits are structured and attached to product information that isn't feasible (I've tried but this is as close as it gets, long story short is that it's not really possible to make a unique list of benefits and/or products in a way that keeps the information correct).
What I want in power Bi is a matrix that shows each contract, which can expand to show all of their product benefits for their current product, and check whether each benefit is new (based on the previous product id):
Essentially, I want a measure that finds:
For each contract
For each product they have
For each benefit in that product
Check if that benefit exists in their previous product and return yes/no
I've started with a measure using SELECTEDVALUE() to find the product id, previous product id, and the specific benefit name, I define each as a variable in the measure to reuse later. When I test each of these values in a matrix they all come out properly alongside the correct contract/product/benefits (i.e. return each SELECTEDVALUE() separately and display them in the matrix, values are correct).
That's where it starts to not work properly. I've tried a lot of options ( TREATAS, CONTAINS, FILTER, CALCULATETABLE etc.) but nothing seems to want to give me what I expect. I've managed to get partway there with GENERATE, generating a table from contract product and a filtered version of benefits to only the SELECTEDVALUE of the previous_product_id, if I COUNTROWS on this it gives me the right number for the previous product, but any time I try to then also apply a filter for the specific benefit into that generated table, or check if it contains the value, it goes wrong (errors, blank tables, or a massive expansion where it shows every single benefit, with most of them blank and only the benefits from the previous product populated).
Thanks in advance for any suggestions.
You could try the following.
Create a second inactive relationship with previous_product_id
.
Then create a measure similar to:
New Option =
var curOptions = DISTINCT(Benefit[benefit_name])
var prevOptions =
CALCULATETABLE(
DISTINCT(Benefit[benefit_name]),
USERELATIONSHIP(Contract[previous_product_id], Benefit[product_id])
)
var chk = COUNTROWS( INTERSECT(curOptions, prevOptions) )
return
SWITCH( TRUE(),
NOT ISINSCOPE(Benefit[benefit_name]), "",
ISBLANK(COUNTROWS( curOptions )), BLANK(),
ISBLANK(chk), "Yes",
"No"
)
Or this measure depending on which you are after (see results below):
New Option v2 =
var curOptions = DISTINCT(Benefit[benefit_name])
var curProducts = DISTINCT(Contract[product_id])
var prevOptions =
CALCULATETABLE(
DISTINCT(Benefit[benefit_name]),
NOT Benefit[product_id] IN curProducts,
USERELATIONSHIP(Contract[previous_product_id], Benefit[product_id])
)
var chk = COUNTROWS( INTERSECT(curOptions, prevOptions ) )
return
SWITCH( TRUE(),
NOT ISINSCOPE(Benefit[benefit_name]), "",
ISBLANK(COUNTROWS( curOptions )), BLANK(),
ISBLANK(chk), "Yes",
"No"
)