Trouble counting occurence of values between 3 connected columns - powerbi

I am having tremendous difficulty in getting around a Power BI function.
I am super new to Power BI and I've learned a lot already but I'm still confused about some topics.
I uploaded some data from excel into my Power BI applicaiton and it had some data as such.
Returns (Tab 1)
Order ID (column 1)
1
2
3
Orders (Tab 2)
Order ID (column1) Product ID (column 2)
1 100
1 101
2 101
3 101
3 100
4 100
Product (tab 3)
Product ID (column 1) Product(column 1)
100 Table
101 Chair
What I am trying to do is figure out the top 5 products that are returned.
I know the data above only has 2 products, but the actual data in my Power BI file has many more.
I basically want to take the Order ID from tab 1, compare them with the multiple product ID's each order has in tab 2 and then compare that with the product names in tab 3 to figure out the top 5 products that are returned.
I've already establihed all the relationships and linkages.
I've tried to use the "Top N", count distinct and sum functions but I was unable to get the filteration mechanism to work properly.
I kept on getting the total number. I also tried using matrix but that didn't work either.
You can access the file with this[link][1] in case anyone wants to look at the data I am working with to get a better idea of my problem. Page 3 is where majority of my attempts have been at trying to solve the problem.
I'm basically trying to find the top 5 most returned products, ideally in a graph and maybe using a slicer.
https://1drv.ms/u/s!AnMQvyG3G5w6iTcKZUaBvA_oLalv
That link above leads to the download page to downloads the PBIX file I am working with.
I would greatly appreciate any help.

First create a Table using this below DAX-
minimum_return_show =
VAR return_per_product_name =
SUMMARIZECOLUMNS(
Products[Product Name],
"return", count(Products[Product Name])
)
var top_n =
MINX(
TOPN(
5,
return_per_product_name,
[return]
),
[return]
)
return
TOPN(
1,
FILTER(
return_per_product_name,
[return] >= top_n
),
[return],
ASC
)
Now create a Measure as below-
product_count =
if(
count(Products[Product Name]) >= max(minimum_return_show[return]),
count(Products[Product Name]),
0
)
Finally create your bar chart using column product_name and measure product_count. Apply filter on product_count with greater than 0 and hopefully you will get your desired output.

Related

Power BI - Filtering model on latest version of all attributes of all dimensions through DAX

I have a model that's comprised of multiple tables containing, for every ID, multiple rows with a valid_from and valid_to dates.
This model has one table in that is linked to every other table (a table working as both a fact and a dimension).
This fact has bi-directional cross filtering with the other tables.
I also have a date dimension that is not linked to any other table.
I want to be able to calculate the sum of a column in this table in the following way:
If a date range is selected, I want to get the sum of the latest value per ID from the fact able that is before the max selected date from the date dimension.
If no date is selected, I want to get the sum of the current version of the value per ID.
This comes down to selecting the latest value per ID filtered on the dates.
Because of the nature of the model (bi-directional with the fact/dimension table), I want to have the latest version of any attribute from any dimension selected in the visual.
Here's an data example and the desired outcome:
fact/dimension table:
ID
Valid_from
Valid_to
Amount
SK_DIM1
SK_DIM2
1
01-01-2020
05-12-2021
50
1234
6787
1
05-13-2021
07-31-2021
100
1235
6787
1
08-01-2021
12-25-2021
100
1236
6787
1
12-26-2021
12-31-2021
200
1236
6787
1
01-01-2022
12-31-9999
200
1236
6788
Dimension 1:
ID
SK
Valid_from
Valid_to
Name
1
1234
10-20-2019
06-01-2021
Name 1
1
1235
06-02-2021
07-31-2021
Name 2
1
1236
08-01-2021
12-31-9999
Name 3
Dimension 2:
ID
SK
Valid_from
Valid_to
Name
1
6787
10-20-2019
12-31-2021
Name 1
1
6788
01-01-2022
12-31-9999
Name 2
My measure is supposed to do the following:
If no date is selected than the result will be a matrix like the following:
Dim 1 Name
Dim 2 Name
Amount Measure
Name 3
Name 2
200
If July 2021 is selected than the result will be a matrix like the following:
Dim 1 Name
Dim 2 Name
Amount Measure
Name 2
Name 1
100
So the idea here is that the measure would filter the fact table on the latest valid value in the selected date range, and then the bi-directional relationships will filter the dimensions to get the corresponding version to that row with the max validity (last valid row) in the selected range date.
I have tried to do the following two DAX codes but it's not working:
Solution 1: With this solution, filtering on other dimensions work and I get the last version in the selected date range for all attributes of all used dimensions. But the problem here is that the max valid from is not calculated per ID, so I only get the max valid from overall.
Amount Measure=
VAR _maxSelectedDate = MAX(Dates[Dates])
VAR _minSelectedDate = MIN(Dates[Dates])
VAR _maxValidFrom =
CALCULATE(
MAX(fact[valid_from]),
DATESBETWEEN(fact[valid_from], _minSelectedDate, _maxSelectedDate)
|| DATESBETWEEN(fact[valid_to], _minSelectedDate, _maxSelectedDate)
)
RETURN
CALCULATE(
SUM(fact[Amount]),
fact[valid_from] = _maxValidFrom
)
Solution 2: With this solution, I do get the right max valid from per ID and the resulting number is correct, but for some reason, when I use other attributes from the dimensions, it duplicates the amount for every version of that attribute. The bi-directional filtering does not work anymore with Solution 2.
Amount Measure=
VAR _maxSelectedDate = MAX(Dates[Dates])
VAR _minSelectedDate = MIN(Dates[Dates])
VAR _maxValidFromPerID =
SUMMARIZE(
FILTER(
fact,
DATESBETWEEN(fact[valid_from], _minSelectedDate, _maxSelectedDate)
|| DATESBETWEEN(fact[valid_to], _minSelectedDate, _maxSelectedDate)
),
fact[ID],
"maxValidFrom",
MAX(fact[valid_from])
)
RETURN
CALCULATE(
SUM(fact[Amount]),
TREATAS(
_maxValidFromPerID,
fact[ID],
fact[valid_from]
)
)
So if somebody can explain why the bi-directional filtering doesn't work anymore that will be great, and also, more importantly, if you have any solution to have both the latest value per ID and still keep filtering on other attributes, that would be great!
Sorry for the long post, but I thought it's best to give all the details for a complete understanding of my issue, this has been picking my brain since few days now and I'm sure I'm missing something stupid but I turned to this community for help because I cannot seem to be able to find a solution!
Thank you very much in advance for any help!
Seems to be workable with a dummy model. I didn't got the point how filter ID, so if it creates a problem let me know how you handle ID. Then I changed fact to facts as fact is a function. Also, I'm not sure about the workability of the measure at your real model. Hope you will give some feedback.
Amount Measure =
VAR ValidDate=
calculate(
max(facts[Valid_to])
,ALLEXCEPT(facts,facts[ID])
,facts[Valid_to]<=MAX(Dates[Date])
)
Return
CALCULATE(
SUM(facts[Amount])
,TREATAS({ValidDate},facts[Valid_to])
)

Power BI - Need a slicer to look at multiple columns of Data

I am learning PowerBI as i go along and have been able to solve most issues faced by a quick google. Unfortunately this problem has baffled me.
We have thousands of lines of data which include a "Home Country" column & "Away Country" column.
What we need our slicer to do is to is to pick up for example Australia in both of these columns and display the results.
I currently have a table created using the below:
slicercountrytable = distinct(
Union(
Values('All Data'[Home Country]),
Values('All Data'[Away Country])))'''
and then a measure:
Measure =
if(
Min('All Data'[Home Country]) in values (slicercountrytable[Country])
|| Min('All Data'[Away Country]) in values (slicercountrytable[Country]),
1,
Blank()
)
And have also tried the below measure:
Measure 3 = VAR
Searchvalue=search(SELECTEDVALUE(slicercountrytable[Country]),SELECTEDVALUE('All Data'[Combined Country]),,Blank())
Return
If(Searchvalue > 0,"Found")
I need the slicer to control the entire sheet however the above are doing nothing.
Thanks
In that case, instead of building some complicated DAX I suggest to work the model.
Let's say your current table looks like that:
id
home country
away country
1
A
B
2
B
C
You may want to deal with that in another table by unpivoting home_country and away_country in PowerQuery.
In order to have a country table like that:
id
country
attribute
1
A
home
1
B
away
2
B
home
2
C
away
Then you link this new table to your existing one on id and filter/slice in it.
I reproduced your example and feel that it is already showing the desired behavior. I think the problem you might be running into is that you will now need to add your 'measure' filter to each and every visual individually. It cannot be added to 'Page' or 'All Pages' filter areas. This is because of the way a measure's calculation varies across context and cannot be avoided.
DAX
Table 2 = distinct(union(all('Table'[Away]), all('Table'[Home])))
Measure =
if(
MAX('Table'[Away]) in VALUES('Table 2'[SelectedCountries])
|| MAX('Table'[Home]) in VALUES('Table 2'[SelectedCountries]) ,
1,
blank()
)

In PowerBI what options are there to hide/redact/mask values in visuals to anonymise data

What options are there in PowerBI to suppress, redact or hide values to anonymise values in reports and visuals without loosing detail and have that restriction apply to multiple pages in a report?
Cat
Count
%
Category 1
23
10
Category 2
2
0.9%
Category 3
4
1.7%
So that its possible to keep the rows but end up with a placeholder where count is <4 and % is greater than 1% but less than 2%
Cat
Count
%
Category 1
23
10
Category 2
*
0.9%
Category 3
4
*
So far my experience has been
a measure with a filter applied will hide rows but you can't apply a measure filter to an entire page or all report pages.
Ive seen mention of conditional formatting to hide the value by having the font and background the same colour but that seems open to error and labour intensive.
I also want to be clear when a value has been suppressed or masked
I suspect there is a more better way but I haven't been able to figure out where to even start.
OK, I have something working but you will need Tabular Editor to create a calculation group. Here are the steps.
I'm using the following table (named "Table") as the source data.
Add two measures (calculation groups only work on measures) as follows.
% Measure = SUM('Table'[%])
Count Measure = SUM('Table'[Count ])
Open tabular editor and create a new calculation group named "CG" with a calculation item named "Mask". Paste the following code into the calculation item.
if (
(selectedmeasurename() = "% Measure" && selectedmeasure() >1 && selectedmeasure() <2)
||
(selectedmeasurename() = "Count Measure" && selectedmeasure() <4)
,"*",selectedmeasure()
)
4. Save the calculation group and in Power BI drag the name column onto the filter for all pages as follows, ensuring it is selected:
The masking will now happen across all reports automatically. Below you can see the same table on two different reports which have now been successfully masked.
It depends on your data connection type as to whether this is available, but a calculated column (instead of a measure) can be used as a filter at the "this page" or "all pages" level.
If this option is available, then you can find it right next to the "New Measure" field.
Using this and your sample data above, I created a couple of calculated columns and show the resulting table. You can then display these columns and use them as filters throughout the report. Your DAX may be slightly different depending on how the actual data is formatted and such.
Count Calculated Column
Masked Count =
IF(
'Table'[Count] < 4,
"*",
CONVERT('Table'[Count], STRING)
)
% Calculated Column
Masked % =
IF(
'Table'[%] > .01 && 'Table'[%] < .02,
"*",
CONVERT('Table'[%] * 100, STRING) & "%"
)
Resulting Table
Example of how the filter can be used
The values of these columns will update as your data source is refreshed in Power BI. However, calculated columns aren't available for Live Connection, in which case you would have to do this kind of logic at a lower level (in Analysis Services for example).
Additionally, you could potentially use Power Query Editor to accomplish this kind of thing.

Is there a way to filter a table based on criteria from another table in Power BI using DAX?

So, I have two tables, Scores and Accounts.
ID
Score
1
120
2
150
3
100
ID
Account
1
Account 1
2
Account 2
3
Account 3
I also have 4 measures that calculate the quartile percentile for all of the scores in the Scores table. I was wondering if it was possible to have a measure that concatenates the accounts into one line if their score is, for example, greater than the Quartile 1 measure. For example, if quartile 1 is 110, then I want a measure that would give me "Account 1, Account 2". Is this possible?
I managed to get your result by implementing the following measure, assuming you have a relationship between the two tables.
Accounts GT Q1 =
CONCATENATEX(
FILTER(
Scores,
Scores[Scores] > [Quartile 1]
),
RELATED( Accounts[Account] ),
", "
)
Output
There may be a simpler way. Let me know if that worked.

DAX selecting and displaying the max value of all selected records

Problem
I'm trying to calculate and display the maximum value of all selected rows alongside their actual values in a table in Power BI. When I try to do this with the measure MaxSelectedSales = MAXX(ALLSELECTED(FactSales), FactSales[Value]), the maximum value ends up being repeated, like this:
If I add additional dimensions to the output, even more rows appear.
What I want to see is just the selected rows in the fact table, without the blank values. (i.e., only four rows would be displayed for SaleId 1 through 4).
Does anyone know how I can achieve my goal with the data model shown below?
Details
I've configured the following model.
The DimMarket and DimSubMarket tables have two rows each, you can see their names above. The FactSales table looks like this:
SaleId
MarketId
SubMarketId
Value
IsCurrent
1
1
1
100
true
2
2
1
50
true
3
1
2
60
true
4
2
2
140
true
5
1
1
30
false
6
2
2
20
false
7
1
1
90
false
8
2
2
200
false
In the table output, I've filtered FactSales to only include rows where IsCurrent = true by setting a visual level filter.
Your max value (the measure) is a scalar value (a single value only). If you put a scalar value in a table with the other records, the value just get repeated. In general mixing scalar values and records (tables) does not really bring any benefit.
Measures like yours can be better displayed in a KPI or Multi KPI visual (normally with the year, that you get the max value per year).
If you just want to display the max value of selected rows (for example a filter in your table), use this measure:
Max Value = MAX(FactSales[Value])
This way all filter which are applied are considered in the measures calculation.
Here is a sample:
I've found a solution to my problem, but I'm slightly concerned with query performance. Although, on my current dataset, things seem to perform fairly well.
MaxSelectedSales =
MAXX(
FILTER(
SELECTCOLUMNS(
ALLSELECTED(FactSales),
"id", FactSales[SaleId],
"max", MAXX(ALLSELECTED(FactSales), FactSales[Value])
),
[id] = MAX(FactSales[SaleId])
),
[max]
)
If I understand this correctly, for every row in the output, this measure will calculate the maximum value across all selected FactSales rows, set it to a column named max and then filter the table so that only the current FactSales[SaleId] is selected. The performance hit comes from the fact that MAX needs to be executed for every row in the output and a full table scan would be done when that occurs.
Posted on behalf of the question asker