Cannot figure out how to get RANKX to work - powerbi

I have been struggling with this for the past two days. I am trying to use Power BI to create a simple report to show the top 10 occurrences of something.
I have a table called Requests that has the following:
Id Code
1 00001
2 00001
3 00500
4 00001
5 00500
6 00730
...
I am trying to count every occurrence of Code and display the top 10:
Code Count Rank
00001 3 1
00500 2 2
00730 1 3
I created a measure called Count:
Count = COUNTROWS(Requests)
I tried to create a measure for rank in the following ways:
Rank = RANKX(ALL(Requests), [Count])
Rank = RANKX(Requests, [Count])
Everything is getting the same value of 1:
Code Count Rank
00001 3 1
00500 2 1
What am I doing wrong?

You can use the built-in Top N Filter if you don't want too much hassle. Just set a Top N Filter for the Code column showing top 10 by value of Count:

I believe the reason you get all 1's is that the measure you created will just give you the total number of rows in your table each time it's used, and then you basically try to rank the same number against itself over and over, for each row.
You can get what you want by using TOPN and then RANKX. To do that, create a new table and enter this code to get the top 10 Codes from the Requests table, based on Id counts:
TOP10 = TOPN(10,GROUPBY(Requests,Requests[Code],"Count",countx(CURRENTGROUP(),Requests[Id])))
Then add a new column with this code to do the ranking:
Rank = RANKX(TOP10,TOP10[Count])
You'll get this result from your first 6 rows that you showed above:

Consider using VALUES and a variable for a calculated table in Power BI Desktop:
Top 10 Codes =
VAR MyTable =
ADDCOLUMNS (
VALUES ( Requests[Code] ),
"Occurences", COUNTROWS ( RELATEDTABLE ( Requests ) )
)
RETURN
TOPN (
10,
ADDCOLUMNS ( MyTable, "Rank", RANKX ( MyTable, [Occurences] ) ),
[Rank], ASC
)

Related

Can we compare a row value with another row value in the table and highlight it in Power BI?

I have a table where 3 columns can have same value
Example:
Name Score_a Score_b Score_c
A 12 15 18
B 3 3 3
C 20 25 30
I want to highlight ( with a colour ) the row B since all the three scores are same.
I am unable to do it with conditional formatting available.
Can something be worked out using DAX? Please help!
Yes, first create a measure using the following dax formula:
Measure =
IF(
SELECTEDVALUE( 'Table'[Score_a] ) = SELECTEDVALUE( 'Table'[Score_b] ) &&
SELECTEDVALUE( 'Table'[Score_b] ) = SELECTEDVALUE( 'Table'[Score_c] ), 1, 0
)
Then you need to use conditional format on every column that you want to highlight and select the Measure you created.
This is the result

Sum distinct values for first occurance in Power BI with Filter

In Power BI I have some duplicate entries in my data that only have 1 column that is different, this is a "details" column.
Basically, when I sum up my Value column on a Power BI card, I want it to filter IsActive = 1 and sum for each unique name, so in this case:
Total= 10 + 7
Is there any way I can filter this with a DAX formula?
Assuming your table can also have a row with the same value of another row but a different name, and a row where Details column doesn't always include "Feature 1"
Name Values Details IsActive
Item 1 10 Feature 1 1
Item 1 10 Feature 2 1
Item 2 15 Feature 1 0
Item 3 7 Feature 1 1
Item 3 7 Feature 2 1
Item 3 7 Feature 3 1
Item 4 10 Feature 1 1
Item 5 10 Feature A 1
then we should use the Name column an write something like follows
Total =
CALCULATE(
SUMX( SUMMARIZE( T, T[Name], T[Values] ), T[Values] ),
T[IsActive] = 1
)
You can create a calculated column wherein you rank the rows based on the occurrence via M-query as provided in the below link :
https://community.powerbi.com/t5/Desktop/How-to-add-Row-number-over-partition-by-Customer-DAX-or-M-query/td-p/566949
Once the calculated column is done, you can achieve your result based on the below measure :
sum(value) where IsActive=1 and calculatedColumn=1 via on Filter DAX
It doesn't appear that the first occurrence is relevant, so you can just write a measure to sum distinct values.
SUMX (
CALCULATETABLE (
VALUES ( Table1[Value] ),
Table1[IsActive] = 1
),
Table1[Value]
)

DAX Measure for SQL NOT EXISTS

I would like to add an incremental refresh for one of our biggest transactional tables.
This transactional table has this structure:
Order
Value
Index1
Index2
100
5
1
0
101
5
2
0
102
6
3
0
103
2
4
0
103
3
5
4
104
4
6
0
Order: The order number
Value: The order value
Index1: Row Index total
Index2: Row Index, which should be replaced
As you can see in order 103, there are two rows in (Index1: 4 &5). The booking with Index1 = 5, is the correction booking. That means that the row with Index1= 4 should be filtered out.
The SQL code I am using to filter all false entries is this one:
SELECT DBA1.Order,
DBA1.Value
FROM AZ.SC DBA1
WHERE NOT EXISTS (SELECT *
FROM AZ.SC DBA2
WHERE DBA2.INDEX2 = DBA1.INDEX1)
Since this SQL will not allow "Query Folding" which is necessary for PBI Incremental refresh, I need somehow an approach within a DAX Measure, that will filter also all false entries. But how?
Please let me know if you need further information.
If your idea is to import all of the rows and later filter the fact table keeping only the updated ones, a possible solution is to add a calculated column to be used in any measure that uses the fact table, stating if the row is to be considered or not. This can be achieved for instance with the following DAX code
IsValid =
VAR CurrentIndex = CALCULATETABLE( VALUES( SC[Index1] ) )
VAR RemovedIndexes = ALL( SC[Index2] )
RETURN
IF (
ISEMPTY( INTERSECT(CurrentIndex, RemovedIndexes) ),
1,
0
)
Otherwise, if the idea is to compute a calculated table with the older rows filtered out a possible implementation is
SC Filtered =
VAR AllIndexes = ALL( SC[Index1] )
VAR RemovedIndexes = ALL( SC[Index2] )
VAR ValidIndexes = EXCEPT( AllIndexes, RemovedIndexes )
RETURN
SUMMARIZECOLUMNS(
SC[Order],
SC[Value],
TREATAS( ValidIndexes, SC[Index1] )
)
But this might waste a lot of memory, since it almost duplicates the fact table.

DAX query for counting values based on another cumulative DAX measure

I have this table:
Id Length(m) Defect Site Date
1 10 1 y 10/1/19
2 60 0 x 09/1/19
3 30 1 y 08/1/19
4 80 1 x 07/1/19
5 20 1 x 06/1/19
I want to count the amount of defects and ids that are in the last 100m of length(sorted by date DESC), whilst maintaining the ability for this to change with additional filters. For example, what are the amount of defects for site x in the last 100m, or what are the amount of defects in the last 100m that have an ID bigger than 1.
For the question 'What are the amount of defects for site x in the last 100m', I would like the result to be 2, as the table should look like this:
Id Length(m) Length Cum. Defect Site Date
4 80 80 1 x 07/1/19
5 20 100 1 x 06/1/19
I believe the issue in creating this query so far has been that I need to create a cumulative DAX query first and then base the counting query off of that DAX query.
Also important to note that the filtering will be undertaken in PowerBI. I don't want to hardcode filters in the DAX query.
Any help is welcome.
Allwright!
I have taken a crack at this. I did assume that the id of the items(?) increments through time, so the oldest item has the lowest id.
You were correct that we need to filter the table based on the cumulative sum of the meters. So I first add a virtual column to the table (CumulativeMeters) which I can then use to filter the table on. I need to break the filter context of the ADDCOLUMNS function to sum up the hours of multiple rows.
Important is to use ALLSELECTED to keep any external filters in place. After this it is pretty straightforward to filter the table on a maximum CumulativeMeters of <= 100 meters and where the row is a defect. Counting the rows in the resulting table gives you the result you are looking for:
# Defects last 100m =
CALCULATE (
COUNTROWS ( Items ),
FILTER (
ADDCOLUMNS (
Items,
"CumulativeMeters", CALCULATE (
SUM ( Items[Length(m)] ),
FILTER (
ALLSELECTED( Items ),
Items[Date] <= EARLIER ( Items[Date] )
&& Items[Id] <= EARLIER ( Items[Id] )
)
)
),
[CumulativeMeters] <= 100
&& Items[Defect] = 1
)
)
Hope that helps,
Jan

How can I create a total that is filtered by selection and slicer?

Problem
I would like to create a multi-layer histogram that shows the distribution of var1 on the first level and var2 on the second level, with a legend by source, like this:
The value should show the percentage w.r.t. the total of a source, with all the selections and slicers applied. The percentages shown in the histogram should always sum to 100% per source.
Example data
I have the following example data:
source var1 var2 count
A 1 1 100
A 1 2 12
A 1 3 34
A 2 1 1612
A 2 2 23
A 2 3 43
B 1 1 200
B 1 2 320
B 1 3 12
B 2 1 1757
B 2 2 345
B 2 3 32
What have I tried
I can achieve a total per source with the following measure without the filtering part:
percPerSource =
DIVIDE(
SUM(input[count]);
CALCULATE(
SUM(input[count]);
ALLEXCEPT(input;input[source])
)
)*100
If I turn on Drill mode and click on the columns of var1 I get the following, undesired result (the percentages do not sum to 100%):
Another attempt was using the ALLSELECTED function:
percSelected =
DIVIDE(
SUM(input[count]);
CALCULATE(
SUM(input[count]);
ALLSELECTED(input[var1])
)
)*100
This shows only 100% on the var2 level:
I think this will do what you're after:
percPerSource =
DIVIDE(
SUM(input[count]);
CALCULATE(
SUM(input[count]);
FILTER(
ALLSELECTED(input);
input[Source] IN VALUES(input[Source])
)
)
)*100
This takes all the selected values as the universe you are filtering on but only selects the rows that in your local filter context.
The FILTER function takes a table as its first argument and a condition as the second argument. It iterates through every row in the table passed into it and checks if the condition holds and returns a table with only the rows where the condition evaluates to True.
The VALUES function returns a list of distinct values of the column specified evaluated within the local filter context.