Power BI - Using a slicer on a Matrix Grand total - powerbi

I have been working on this Power BI Report and would like some assistance with a slicer used for a matrix.
I need the slicers "MB Data Used", "Calls Made", and "SMS Sent" to slice the Matrix Grand Total fields (on the far right) instead of the value fields. My current slicers work great on the value fields.
Data is filled by a table:
----------------------------------------------------
|ph_id | month | data_used | calls_made | sms_sent |
| 1 | 1/1/19| 123 | 0 | 33 |
| 2 | 1/1/19| 87 | 22 | 0 |
| 3 | 1/1/19| 0 | 0 | 0 |
| 1 | 1/2/19| 0 | 55 | 33 |
| 2 | 1/2/19| 87 | 22 | 77 |
| 3 | 1/2/19| 0 | 0 | 0 |
----------------------------------------------------
Which links to a few others to get related data.
My goal is to be able to see which phone numbers have had no data/call/sms use over the last X months instead of just filtering the ones which contain a 0. In this scenario, when the slicers are all set to 0 and the date range is set 1/1/19-1/2/19, only ph_id 3 should show.
Edit:
W.B. - see this image

You need to use another, unrelated table for your slicers. The best way to create such table is to use the what-if parameter option in the modelling tab (assuming you have any recent version of PBI Desktop).
Or, if you want to base the slicer on number of calls from actual data, you would create the slicer table using New table option and the following formula: CallSlicer = GENERATESERIES(MIN(Data[calls_made]), MAX(Data[calls_made]), 1). The one at the end indicates the step, so you can adjust it, if you want your users to use the slicer in, for instance, increments of 10 or 20.
Now, when you use the generated CallSlicer column, which looks like this:
You will be able to filter your results like this: Your filtered measure = CALCULATE([your_measure], FILTER(Data, Data[calls_made] >= MIN(CallSlicer[CallSlicer]) && Data[calls_made] <= MAX(CallSlicer[CallSlicer]))). You then use your filtered measure in the matrix visual.
EDIT:
Here's a working sample: https://1drv.ms/u/s!AmqvMyRqhrBpgtRGGbJ6w-b66uBENQ?e=67JduS
I've updated the sample - now it shows 2 scenarios. One table reacts to the slicer at individual cell level, the other one at the grand total level.
The key to have the first table working is shown above, below is a solution for the second table, that filters rows at the grand total level:
Create a measure that will show sum for all dates/months, as an example:
CallSumTotal =
VAR tab =
FILTER (
CALCULATETABLE (
SUMMARIZE ( Data, Data[id], "calls_made", SUM ( Data[calls_made] ) ),
ALLSELECTED ( Data[month] )
),
[calls_made] >= MIN ( CallSlicer[Value] )
&& [calls_made] <= MAX ( CallSlicer[Value] )
)
RETURN
SUMX ( tab, [calls_made] )
Now in the matrix use a regular sum measure, but create a visual level filter for CallSumTotal and set it to is not blank

Related

PowerBI Additive Slicers (Applied to whole Report)

I have a quite niche problem in regards to PowerBI slicer operations.
I wish to filter the data based on two different slicers.
For example I have two different slicers;
A list of categories, say Genre of Films; and
A list of all film directors
I wish to filter the data shown in the PowerBI report based on an OR condition between the two slicers.
For instance, I wish to filter based on all Horror films OR films directed by Quentin Tarantino. So this list would show all Horror films in my database and all films directed by Quentin Tarantino (that are not necessarily Horror films).
I presume that I will need to write some form of DAX code for this but through substantive searching I have not come across this particular problem.
Let me know if you need any further info.
Regards,
Josh
Let's suppose you have a table called IMDB like following
| tbl-IMDB |
|--------------------------|---------|----------------------|
| Name | Genre | Director |
|--------------------------|---------|----------------------|
| The Shawshank Redemption | Drama | Frank Darabont |
| The Godfather | Crime | Francis Ford Coppola |
| The Dark Knight | Action | Christopher Nolan |
| 12 Angry Men | Drama | Sidney Lumet |
| Schindler's List | History | Steven Spielberg |
| Pulp Fiction | Crime | Quentin Tarantino |
and two more disconnected table for slicers as following
| tbl-Director |
|----------------------|
| Director |
|----------------------|
| Frank Darabont |
| Francis Ford Coppola |
| Christopher Nolan |
| Sidney Lumet |
| Steven Spielberg |
| Quentin Tarantino |
|tbl-Genre|
|---------|
| Genre |
|---------|
| Drama |
| Crime |
| Action |
| History |
the data model looks like this
Now, if I understood your question correctly, when you select {Crime,Action} from Genre and {Sidney Lumet, Steven Spielberg} from Director it should return 5 instances; i.e. leaving only the first instance of -The Shawshank Redemption
In order to get there, first all the slicer combinations are needed to be taken into account and what they can do the table.
a. all the slicer values are selected in Director and Genre slicer - DAX to return the full table.
b. none of the slicer values are selected in Director and Genre slicer - DAX to return the full table because the default behavior of DAX is to return the full table if nothing is selected in the slicer.
c. partial values are selected in Genere and nothing/everything is selected in Director and vice versa -
DAX is to return the full table for example, if Drama is selected (2 instances) + nothing/everything is selected in Director (6 instnaces) -> total 6 instances
d. partial values are selected in both Genere and Director - DAX to return the addition of the instances according to the slicer selection - ;e,g. Drama=2+Sideney Lumet=1 => total 3 instances
The above logic can be incorporated in a DAX measure like following
Measure =
VAR _genre = --- what are the genres selected from Genere Slicer and find them in IMDB tbl
MAXX (
FILTER ( IMDB, IMDB[Genre] IN ALLSELECTED ( Genre[Genre] ) ),
IMDB[Genre]
)
VAR _director = --- what are the directors selected from Director Slicer and find them in IMDB tbl
MAXX (
FILTER ( IMDB, IMDB[Director] IN ALLSELECTED ( Director[Director] ) ),
IMDB[Director]
)
VAR _genreCountALL = -- what are the total count of genere from Genre tbl regardless of the slicer seletion
CALCULATE ( COUNT ( Genre[Genre] ), ALL ( Genre ) )
VAR _directorCountALL = -- what are the total count of director from Director tbl regardless of the slicer seletion
CALCULATE ( COUNT ( Director[Director] ), ALL ( Director ) )
VAR _genreCountSELECT = -- what are the total count of genere from Genre tbl according to slicer seletion
COUNT ( Genre[Genre] )
VAR _directorCountSELECT = -- what are the total count of director from Director tbl according to slicer seletion
COUNT ( Director[Director] )
VAR _slice = --- if Genere and/Director slicer are both selected then return the max else in every other instances it is a full tbl
SWITCH (
TRUE (),
_genreCountALL <> _genreCountSELECT
&& _directorCountALL <> _directorCountSELECT,
CALCULATE (
MAX ( IMDB[Name] ),
FILTER ( IMDB, IMDB[Director] IN { _director } || IMDB[Genre] IN { _genre } )
),
CALCULATE ( MAX ( IMDB[Name] ) )
)
RETURN
_slice
and put a visual level filter like following
The measure produces following
nothing is selected - returns full table
partial values are selected in only one slicer- returns full table
partial values are selected in all available slicers - returns the sliced table

PowerBI DAX – subquery to the same table

I have a table, let's call it Products with columns:
Id
ProductId
Version
some other columns…
Id column is the primary key, and ProductId groups rows. Now I want to view distinct values of ProductId where Version is highest.
I.e. From data set:
Id | ProductId | Version | ...
100 | 1 | 0 | ...
101 | 2 | 0 | ...
102 | 2 | 1 | ...
103 | 2 | 2 | ...
I need to get:
Id | ProductId | Version | ...
100 | 1 | 0 | ...
103 | 2 | 2 | ...
In SQL I would write:
SELECT Id, ProductId, Version, OtherColumns
FROM Products p1
WHERE NOT EXISTS
(SELECT 1
FROM Products p2
WHERE p2.ProductId = p1.ProductId
AND p2.Version > p1.Version)
But I have no idea how to express this in DAX. Is this approach with subqueries inapplicable in PowerBI?
Another approach is to first construct a virtual table of product_ids and their latest versions, and then use this table to filter the original table:
EVALUATE
VAR Latest_Product_Versions =
ADDCOLUMNS(
VALUES('Product'[Product_Id]),
"Latest Version", CALCULATE(MAX('Product'[Version])))
RETURN
CALCULATETABLE(
'Product',
TREATAS(Latest_Product_Versions, 'Product'[Product_Id], 'Product'[Version]))
Result:
The benefit of this approach is optimal query execution plan.
You can use SUMMARIZECOLUMNS to group ProductId and MAX Version.
Then use ADDCOLUMNS to add the corresponding Id number(s), using a filter on the Products table for the matching ProductId and Version. I've used CONCATENATEX here, so that if multiple Id values have the same Product / MAX Version combination, all Id values will be returned, as a list.
EVALUATE
ADDCOLUMNS (
SUMMARIZECOLUMNS (
Products[ProductId],
"#Max Version",
MAX ( Products[Version] )
),
"#Max Version Id",
CONCATENATEX (
FILTER (
Products,
Products[Version] = [#Max Version] && Products[ProductId] = EARLIER ( Products[ProductId] )
),
Products[Id],
","
)
)

Split data into categories in the same row in Power BI

I have a table that contains multiple columns with their named having either the suffix _EXPECTED or _ACTUAL. For example, I'm looking at my sold items from my SoldItems Table and I have the following columns: APPLES_EXPECTED, BANANAS_EXPECTED, KIWIS_EXPECTED, APPLES_ACTUAL, BANANAS_ACTUAL, KIWIS_ACTUAL (The Identifier of the table is the date, so we have results per date). I want to show that data in a table form, something like this (for a selected date in filters:
+------------+----------+--------+
| Sold items | Expected | Actual |
+------------+----------+--------+
| Apples | 10 | 15 |
| Bananas | 8 | 5 |
| Kiwis | 2 | 1 |
+------------+----------+--------+
How can I manage something like this in Power BI ? I tried playing with the matrix/table visualization, however, I can't figure out a way to merge all the expected and actual columns together.
It looks like the easiest option for you would be to mould the data a bit differently using Power query. You can UNPIVOT your data so that all the expected and actual values become rows instead of columns. For example take the following sample:
Date Apples_Expected Apples_Actual
1/1/2019 1 2
Once you unpivot this it will become:
Date Fruit Count
1/1/2019 Apples_Expected 1
1/1/2019 Apples_Actual 2
Once you unpivot, it should be fairly straightforward to get the view you are looking for. The following link should walk you through the steps to unpivot:
https://support.office.com/en-us/article/unpivot-columns-power-query-0f7bad4b-9ea1-49c1-9d95-f588221c7098
Hope this helps.

Dynamically rank a column based on filters

In my Power BI I have the following table
What I want is that when you create a graph and have a filter, the ranking column is modified. An example would be that when I change the ranking and select center, I get it like this:
site | region | nro_trabajos | ranking
----------+--------+--------------+------
OCCORO | centro | 58 | 1
PILCOMAYO | centro | 59 | 2
SICAYA | centro | 71 | 3
.
.
etc
I generate a table that gives me the following ranking. but has ties
the measure is rank_measure, as this image shows
that I can add in this measure so that the tiebreaker is with the alphabetical order of the "site" column and that it still has the region filter?
A calculated column cannot be dynamic with respect to slicers or filters, but you definitely can create a dynamic ranking measure.
ranking =
RANKX (
ALLSELECTED ( Table1 ),
Table1[nro_trabajos],
MAX ( Table1[nro_trabajos] )
)
Edit:
If you want to do tiebreaking, I think the simplest way is to first create a UniqueRank calculated column:
UniqueRank =
RANKX (
Table1,
FORMAT ( Table1[nro_trabajos], "0000" ) & Table1[region] & Table1[site]
)
You put each column that makes up a unique row in the order you want to rank by, formatting any numbers by padded with sufficient zeros so that the numeric ordering matches the alphabetic ordering.
Then simply use this calculated column UniqueRank instead of nro_trabajos in the measure I gave above:
ranking =
RANKX (
ALLSELECTED ( Table1 ),
Table1[UniqueRank],
MAX ( Table1[UniqueRank] )
)

Stacked Column chart that creates buckets

I currently have a bar graph in power-bi. The graph has distinct id's on the x axis and the amount of mail they received on the y axis. In the Table I am using, I have SalesYear, id, and a Val column which has the value 1 in each row. The id shows up multiple times in the table, sometimes more than twice in the same year.
The problem is I want the graph reversed. I would like to bucket people based on how much mail they received. Then use a slicer to see how much they receive per year. I have been struggling to find a solution on my own, would anyone have any ideas on how to approach this.
Table l looks like this:
id | salesYear | Val
10 | 2012 | 1
11 | 2012 | 1
11 | 2013 | 1
10 | 2012 | 1
10 | 2013 | 1
12 | 2012 | 1
12 | 2012 | 1
So in the visualization I want to show that on the x-axis that people who received 1 piece of mail = 0, 2 pieces of mail = 2, 3 pieces of mail = 1. My question is how can i achieve this will a Stacked Column chart. Any suggestions would be greatly appreciated!
15k | Y axis would be amount of people who recieved 1 piece, 2 piece, etc..
14k | _
13k | | |
12k | _| |
11k || | |
10k ||_|_|_________________________
1 2 3 4 5 6 7 8 9 <-AmountOfMailRecieved
1) Starting with your sample data in Power BI.
2) Create a new calculated table that is a distinct list of years from your source table.
Years = DISTINCT(
SELECTCOLUMNS(
Mail,
"SalesYear", Mail[salesYear]
)
)
3) Create another calculated table that crossjoins the year table with a series of integers. Power BI might indicate the [Value] has an error (like it does for me in the picture below), but it works properly.
MailCounts = SELECTCOLUMNS(
CROSSJOIN(Years, GENERATESERIES(1, 20)),
"SalesYear", Years[SalesYear],
"MailReceived", [Value]
)
4) Add a calculated column that counts the number of IDs in the source table that match the year and mail count. For example, the first row is counting how many distinct IDs show up exactly once in the source table for the year 2012; it's 1 because only ID 11 shows up in 2012 once.
PersonCount = CALCULATE(
DISTINCTCOUNT(Mail[id]),
FILTER(Mail,
Mail[salesYear] = EARLIER(MailCounts[SalesYear]) &&
EARLIER(MailCounts[MailReceived]) = CALCULATE(
COUNTROWS(Mail),
FILTER(Mail,
Mail[salesYear] = EARLIER(Mail[salesYear]) &&
Mail[id] = EARLIER(Mail[id])
)
)
)
)
5) Create relationships between your source table and the year table, and then between the year table and the count table. This will allow the creation of a slicer based on the year of your source table to filter the results from the count table.
6) Optionally, you can hide the year field in the source and count tables. After doing that if you desire, create a chart as configured in the picture below
7) Create a slicer from the year table as shown in the picture below.
And that's it. The chart should match with your expected outcome and can be filtered by year.
You'll be using DISTINCTCOUNT either in a measure or a column.
VariableName = DISTINCTCOUNT([AmountofMailReceived])