In Power BI I have an inventory with multiple possible owners for each product.
Example data:
Product
Primary Owner
Backup Owner
Widget 1
Frank
Sally
Widget 2
Sally
John
Widget 3
John
Widget 4
Frank
Anna
Desired result: to display the full inventory in a table, and provide a slicer that users can filter the table with. The slicer would be a list of all owners (both primary and backup), and when a user is selected the table would display any row where that user is present (whether they are present in the Primary Owner or Backup Owner field.
With the above example, if you were to filter by John you would see Widget 2 and Widget 3, whereas filtering by Sally would show you Widget 1 and Widget 2.
Failed attempts: Using two distinct slicers does not work for this, as it will hide data in the other column. If John were to filter to himself as Primary Owner, he would then no longer see data for Widget 2 where he is the Secondary Owner. Concatenating the Primary and Secondary together into a joined column also does not work, because I would get items like Frank|Sally or Sally|John and the combined data does not make sense for the user as an option in the Slicer.
Finally I tried creating a separate table that contains the combined list of all Primary and Secondary Owners into a single column, then relating it to the main table, however I cannot have two active relationships at once. I know Measures have access to inactive relationships through Calculate, but I don't know how (or if it is even possible) to create a slicer from that.
Edit: After re-reading your post, it would probably make sense to calculate a new table to handle this. The table will have two columns, Product and Person (or Owner in your case):
Slicer Table =
UNION (
SELECTCOLUMNS (
FILTER( 'Table' , 'Table'[Primary Owner] <> BLANK() ) ,
"Product" , 'Table'[Product] ,
"Person" , 'Table'[Primary Owner]
),
SELECTCOLUMNS (
FILTER ( 'Table' , 'Table'[Backup Owner] <> BLANK() ) ,
"Product" , 'Table'[Product] ,
"Person" , 'Table'[Backup Owner]
)
)
After this has been calculated, create a relationship between these tables, between the Product columns. Since this is purely for filtering the table on the person of interest, make it be Many-to-Many and have Slicer Table filter Table:
Create a slicer with the Person column from the Slicer Table and test the functionality:
Related
I need to create a kind of dynamic DAX view based on another DAX table.
First Table
Year, Category, Sub-category, Sales, Sub-Category Weight
I need to do a intermediary step different calculation for Sales on another table that looks at the above table however I can't work out how to do do it. I have a slicer populated with a subcategory dimension on the tab so every time I make a change I need the below table to reflect the chosen sub category but without it being in the table.
Second Table
Year, Category, Sub-category, Sales, Category Weight filtered by Sub-Category
I have tried the following functions:
Summarize
SummarizeColumns
CalculateTable
(think there are more)
I have tried to use each with a filter based on the slicer but I can't get it to work.
Here I have two tables:
Table A: col_A, col_B, col_C, metric_1, metric_2, metric_3
Table B: col_A, col_B, col_C, metric_X, metric_Y, metric_Z
I may need to put them in the report with col_A, col_B, col_C as shared filters. col_A, col_B, col_C are many to many relationship, for example, age, country, domain. How could I achieve this?
The solutions I may know are:
Pull column col_A, col_B, col_C as filters from table 1, but in this case table 2 doesn't have any relation with table 1 and the filter won't work for table 2. And if I add relation of table 2 with table 1 for col_A, then I couldn't next also add relation for col_B or col_C as only one relation could be added.
Another solution is that I would extract col_A, col_B, col_C as a new table for dimensions shared between table 1 and table 2. Then the filters may have better performance as there is less data. However, how could I apply the shared dimension table filter to table 1 and table 2? Or is there way like filter could achieve this?
ForAll(Table1, Collect(col_A, Filter(Table2, col_A in FullName).FullName))
Thanks.
In my opinion, you have two main choices here:
Calculate common dimension tables separately for each Col_A, Col_B, Col_C
Create a common key in each Table A, Table B and create one common dimension table
Common dimension tables for each column
For my simplified model of just two common columns, I have created one separate table per dimension:
The code to create Dim_A is just to use DISTINCT and UNION to get all the possible values from both tables:
Dim_A =
DISTINCT (
UNION (
DISTINCT ( 'Table A'[Col_A] ) ,
DISTINCT ('Table B'[Col_A] )
)
)
It is common to hide the key columns on the many-side of relationships, so I have done that in the model too.
This is the approach I would use if this were my data model, especially if Table A and Table B have columns that are somehow related to Col_A, Col_B, Col_C and give these important context. This approach leaves you with greater freedom to normalize your data model.
Common key in each table
In Power Query (or where you define your tables), add a column that concatenates the important columns into one key column. In Power Query you can simply add a new custom column and the formula will be:
[Col_A]&[Col_b]&[Col_C]
You need this common column in BOTH tables, since Power BI does not allow relationships formed by a combination of columns, only single-column relationships. Once this is done, you add a single table in the data model using the same style of DAX code as used previously, but you now also need more columns for it to make sense:
Dim_All =
DISTINCT (
UNION (
SELECTCOLUMNS (
'Table A' ,
"Key" , [Key] ,
"Col_A" , [Col_A] ,
"Col_B" , [Col_B]
),
SELECTCOLUMNS (
'Table B' ,
"Key" , [Key] ,
"Col_A" , [Col_A] ,
"Col_B" , [Col_B]
)
)
)
Connect your tables using the Key columns, but make sure to specify the correct 1-many setting, depending on your data it might create a 1-1 relationship instead, but you want to avoid this for this data model.
You need to create shared dimension tables and a star schema. When you create the appropriate 1-to-many relationships, the filter will propagate automatically for you.
I have the following two tables:
I would like to add a calculated column to the Author table showing the total number of pages in all the books the author has written.
In SQL I would solve the problem by writing a view like this (or using that code in a trigger to populate the calculated column):
SELECT
"Author"."Author ID"
(SELECT sum("Page count") FROM Book WHERE "Author ID" = "Author"."Author ID") AS "Total pages"
FROM "Author";
How to achieve something like that in Power BI?
Since you want to add the column to the dimension table (one side of the one-to-many relationship) you'll have to use RELATEDTABLE() instead of the RELATED() function:
Page Count = SUMX(
RELATEDTABLE(Book),
Book[Page Count]
)
The row context in your calculated column gets transfered to a filter context in the fact table (Books). This feature is know as context transition.
Of cause your SQL would rather return a table like this one:
Author Pages =
SELECTCOLUMNS(
Author,
"Author ID", Author[Author ID],
"Page Count", SUMX(
RELATEDTABLE(Book),
Book[Page Count]
)
)
However, if you are just interested in visualizing the numbers you don't need any of the above expressions, but just have to drag Author ID and Page Count into a Table visual.
I have two tables, once for slicer and other one is for details table. The details table have a InvoiceDate column where some rows have blank InvoiceDate. The slicer table looks like below:
The slicer will only show value of of ID 1, like below.
Initially I want slicer to be un checked and the data should show only rows where InvoiceDate is Blank. Once User select the Slicer as Include Invoiced Records, it should show both full details i.e. Rows with Blank + Non-Empty dates rows.
There are two other ways of doing what you want that are probably more 'correct' but I'll also describe a way to provide the behavior you describe.
Option one: Delete your second table. Add a calculated column to your details table as follows:
Invoice Status = IF (ISBLANK([Invoice Date]) = TRUE(), "Not yet invoiced", "Invoiced")
Create a slicer using [Invoice Status] and simply default it to show 'not invoiced.' If users want to see the invoiced records, they just check that box in the slicer as well.
Option Two: Use Bookmarks and buttons to produce the desired effect. Create two buttons, one that says 'Include Invoiced Customers' and another that says 'Hide Invoiced Customers' -- create two bookmarks where one has the invoiced customers filtered out of the visual and one where the invoiced customers aren't filtered. Set each button's "Action" to the appropriate bookmark.
Option Three Keep your 'slicer' table. Let's assume it's called 'Invoice Filter Selection.' Create a new measure:
IncludeDetailFilter =
IF (ISFILTERED('Invoice Filter Selection'[Value]) = True(),
1,
IF (ISBLANK(MAX(InvoiceDetails[Invoice Date])) = TRUE(), 1, 0)
)
When the slicer has a selection, it will be considered 'Filtered' and you will pass into the first branch of the IF where the measure always evaluates to 1. When the slicer isn't selected, the measure will evaluate to 1 or 0 depending on whether or not there are any values for Invoice Date in the row. Add this new measure as a filter on your invoice detail visual.
Unchecked:
Checked:
Hope it Helps.
I have a customer service ticket list and need to build a report with it, one of the charts must be a "Qty per motive" and the problem is that I have too many motive to show on a chart, so I want to show let's say 10 of them and wrap the rest on a "Others" categories.
I've found some posts showing hot to do this with values like Sales, but I couldn't figure out how to make it work with a count on my data.
the structure of the data is like
ClientID | Ticket ID | Date | Motive | Description
In the posts that I've found the solution involves a SUM() and then sorting by the SUM() column, but I don't have a value column, I need to count per motive
There are a couple of ways to doing that.
New group
use built-in PBI feature that you have to manually set up. Right-click on a column name in the Fields section and chose New group. A new window will pop up. There, you have to choose the categories you want to label as others. A new field (Column name (groups)) will appear in your table. This method requires you to decide arbitrarily which columns you want to be displayed.
Create calculated table
You could create a brand new Calculated table in your model that is going to set new labels based on the total quantity. In that case, the labels will dynamically change rather than being static. If new motive comes to the model and its quantity will be in TOP N then it will be visible on the chart. This solution creates a separate table that you have to connect via relationship with your main table later.
Select Calculated table on the ribbon and then write DAX:
TopNCategories =
VAR keepLabels = 3
VAR tbl =
ADDCOLUMNS(
VALUES( 'Product'[Brand] ),
"#TotalSales", CALCULATE( [Sales Amount] )
)
VAR addRank =
ADDCOLUMNS(
tbl,
"#Rank",
RANKX(
tbl,
[#TotalSales],
,
DESC
)
)
VAR result =
SELECTCOLUMNS(
addRank,
"BrandKey", 'Product'[Brand],
"NewLabel", IF( [#Rank] <= keepLabels, 'Product'[Brand], "Others" )
)
RETURN
result
Calculated column
If you don't want to create another instance in your model, you can use the above logic to create a set of Calculated column in your main table instead. Depends on your model size and cardinality, this solution may have an impact on the performance of the whole report.