Group By and missing product value DAX Power Query - powerbi

I am new to Power BI and I am trying to solve this challenge on my practice. What is the best way to solve problem like this? Dax or Power Query?
I already solved the unpivoted column to show all the products that Customer had a sales. Now, I wanted to Show all the available products that the customer never sold to.
Example Tables:
Product Table
Product 1
Product 2
Customer Table
Customer 1
Customer 2
Unpivoted Table View
Customer Sold Products
Customer 1 Product 1
Customer 1 Product 2
Customer 2 Product 3
Customer 3 Product 4
Desired Output
Customer Products Possible to Sold to each Customer
Customer 1 Product 3
Customer 1 Product 4
Customer 2 Product 1
Customer 2 Product 2
The Current Solution that I've got is Merging the Sales to the Products table and get all the items that never sold. But I wanted to see all of the available products that never sold to the Customer Level. Any help will be appreciated.

In M/PowerQuery you can just do a merge (using left anti join) on a table of all the possible combinations against the table of ones they sold
Code for query Missing, based on Product, Customer and SoldTo queries
let Source = Customer,
#"Added Custom" = Table.AddColumn(Source, "Product", each Product),
AllPossibleCombinations = Table.ExpandTableColumn(#"Added Custom", "Product", {"Column1"}, {"Product"}),
#"Merged Queries" = Table.NestedJoin(AllPossibleCombinations, {"Column1", "Product"}, Soldto, {"Customer", "Sold Producsts"}, "Soldto", JoinKind.LeftAnti),
#"Removed Columns" = Table.RemoveColumns(#"Merged Queries",{"Soldto"})
in #"Removed Columns"

Related

Problem with date recognition in Power BI

I'll explain my problem with an example:
I have three tables: one of dates, another of employees and another of departments.
There are two relationships:
dim_date[date_id] -> dim_employee[start_date_id]).
dim_department[department_id -> dim_employee[current_department_id]
dim_employee
name
current_department_id
start_date_id
Employee 1
1
20210701
Employee 2
2
20210701
Employee 3
2
20210901
Employee 4
1
20220201
Employee 5
2
20220201
dim_department
department
department_id
Purchase department
1
Sales department
2
I want to count how many employees each department had, for example, in February 2022 (using a slicer).. I've tried this:
num_employees_purchase_department =
CALCULATE(
DISTINCTCOUNT(dim_employee[employee_id]),
dim_employee[current_department_id]=1
)
However, since the relation is made through start_date_id, I only get the new hires of each department (one for the sales department and one for the purchase department) and not the total number of hired personnel.
The result that I'm looking for:
Employees in Purchase Department: 2
Employees in Sales department: 3
Thank you so much!
Try to make dim_date - dim_employee relationship inactive (in Data model view) and add an extra condition into your measure:
CALCULATE(
DISTINCTCOUNT(dim_employee[name]),
dim_employee[start_date_id] <= MAX(dim_date[date_id])
)
Don`t forget to use USERELATIONSHIP() inside your other measures where active dim_date - dim_employee relationship is necessary.

In a matrix table in Power BI, how to make sure that the table doesn't calculate subtotals and totals for duplicates?

I have a matrix table in Power BI where the lowest heirarchy has 2 users with same product but for their manager, it needs to be only counted once. How can I do that in the matrix table?
When I was pulling the heirarchy from one table and sales from another, Power Bi was doing it on it's own but when sales is in the same table as the user heirarchy, it is simply taking a sum of all the sales when it should only sum once for cases when product is repeated for multiple users for the same manager.
As seen in the image, manager's total should be 300 but Power BI sums it up to 400. How can I make sure that manager's total is taken as 300? I'd really appreciate any help. Thank you
Simply put, you should remove the duplicate items related to manager "A" in the "Product" column. In the real scenario, you need to filter this way for each manager.
You can do this within Power Query:
(notice the table name 'SalesTable')
let
Source = Excel.CurrentWorkbook(){[Name="SalesTable"]}[Content],
#"Filtered Rows" = Table.SelectRows(Source, each [Manager] = "A"),
#"Changed Type" = Table.TransformColumnTypes(#"Filtered Rows",{{"Manager", type text}, {"User", type text}, {"Product", Int64.Type}, {"Sales", Int64.Type}}),
#"Duplicate Removed" = Table.Distinct(#"Changed Type", {"Product"}),
Sales = #"Duplicate Removed"[Sales],
CustomSUM = List.Sum(Sales)
in
CustomSUM

How to calculate average weekly active visitor using DAX in PowerBI

*Take note that Visit 1 means the first visit of the day while Visit 2 means the 2nd visit for the day.
Hello everyone,
I'm trying to calculate average weekly active visitors in PowerBI using DAX.
First, I need to calculate how many unique visitors visit the shop in one week (Mon-Sun). Based on the calendar, 5/10/2022 - 5/13/2022 will be categorized under one week, and 5/16/2022 - 5/18/2022 is another week. So for the week from 5/10/2022 - 5/13/2022, there are 9 unique visitor and for the week from 5/16/2022 - 5/18/2022, there are 3 unique visitors.
Once I found out the unique visitor for respective weeks, then I can get the average weekly active visitor by:
(9+3)/2 = 6 visitors
Hence, the answer for the example in the screenshot will be 6 visitors. The output will be used in card visualization.
Struggling to find the best way to do this, any help or advise will be greatly appreciated!
Sample Data:
https://docs.google.com/spreadsheets/d/10TsJUy-Lkdpb9Eeh5itx-XE59hytC_i5I_6UeLLHS84/edit#gid=0
I don't know enough about DAX (or Power BI) to devise a DAX only solution.
However, you can calculate the Distinct Visitors per week using Power Query M Code (Home=>Transform in Power BI), and then create a Measure to show the Average visitors per week on the card.
Power Query M Code
Edit: Change from computing weeknumber to computing start of week to avoid problems if dates span more than a year, per comment below by #weizer
let
//change next line to whatever your actual source is
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
//Don't need this column for the output
#"Removed Columns" = Table.RemoveColumns(Source,{"Visit"}),
//Set data types
#"Changed Type" = Table.TransformColumnTypes(#"Removed Columns",{{"Visitor ID", Int64.Type}, {"Date", type date}}),
//add custom column referenced to "StartOfWeek" so we can group by week
#"Added Custom" = Table.AddColumn(#"Changed Type", "WeekNumber", each Date.StartOfWeek([Date],Day.Monday), type date),
//Group by week number
// Then aggregate by week range and distinct visitor count
#"Grouped Rows" = Table.Group(#"Added Custom", {"WeekNumber"}, {
{"Date Range", each Date.ToText(List.Min([Date])) & " - " & Date.ToText(List.Max([Date])), type text},
{"Distinct Visitors", each List.Count(List.Distinct([Visitor ID])), Int64.Type}
}),
//Remove unneeded Weeknumber column
#"Removed Columns1" = Table.RemoveColumns(#"Grouped Rows",{"WeekNumber"})
in
#"Removed Columns1"
The Measure for the card will be just a simple Average function:
Distinct Visitors per Week = Average(yourTableName[Distinct Visitors])
VAR days =
SUMMARIZE(
'Sheet1'
,'Sheet1'[Date]
)
VAR Calend=
ADDCOLUMNS(
days
,"week",WEEKNUM('Sheet1'[Date])
)
VAR weeks=
SUMMARIZE(
Calend
,[week]
,"qty",COUNTROWS(VALUES('Sheet1'[Visitor ID]))
)
RETURN
AVERAGEX(
weeks
,[qty]
)

Actual Vs Plan in PowerBI

I am having a problem in PowerBi, where I want to get results for Actual vs Plan. I have 3 tables , Book Sales Table, Plan table and Titles table. I would like the result as in Desired Output table.
Book Sales
Titles
Plan
Desired Output
You can do this in Power Query M Code
Join the Sales and Titles tables to extract the publishing unit for each book type
Add a column representing the start of each month for each sales number
Group by BOM and Unit and aggregage with Sum in case you have multiple sales/unit in a month
Join this last table with the Plan table based on Unit and Date
M Code
let
//Join the Sales and Titles to get the Publishing units
Source = Table.NestedJoin(#"Book Sales", {"Book ID"}, Titles, {"Book Id"}, "Titles", JoinKind.LeftOuter),
#"Expanded Titles" = Table.ExpandTableColumn(Source, "Titles", {"Publishing Unit"}, {"Publishing Unit"}),
//add start of month column to merge with Plan
bom = Table.AddColumn(#"Expanded Titles", "BOM", each Date.StartOfMonth([Invoice Date]),type date),
//Group by unit and bom columns in case you happen to have multiple sales in the same month
#"Grouped Rows" = Table.Group(bom, {"Publishing Unit", "BOM"}, {{"Sales amount", each List.Sum([Sales amount]), type number}}),
//Join with Plan using bom and date as the key
salesVplan = Table.NestedJoin(Plan,{"Business Unit","Date"}, #"Grouped Rows", {"Publishing Unit","BOM"},"joined",JoinKind.FullOuter),
#"Expanded joined" = Table.ExpandTableColumn(salesVplan, "joined", {"Sales amount"}, {"Sales amount"})
in
#"Expanded joined"
This could be done in several different ways, but I would recommend doing this in SQL personally. This means that you can:
Select from all the tables you want to show, into the same table. Lets call it Products.
Then you join in the values that you want on that.
This way, there is no dax calculation that takes time, but rather just something that takes time while you refresh the dataset itself.

Conditional Column to Flag for Presence of Any 1 Survey Type at the Customer ID Level (DAX, PowerBI)

I have a customer fact table similar to the below with a Customer ID and Start Date, then a secondary Survey table that is tied to the fact table on the Customer ID with a one (customer) to many (surveys) relationship.
Customer Table:
Customer ID
Start Date
Customer 12
1/1/2021
Customer 34
1/1/2021
Customer 56
1/1/2021
Customer 78
1/1/2021
Customer 91
1/1/2021
Survey Table:
Customer ID
Survey
Customer 12
Survey A
Customer 12
Survey B
Customer 34
Survey C
Customer 34
Survey D
Customer 56
PWI
Records of customers with surveys will appear in the Surveys table, customers without obviously won't appear there just yet.
My goal is to create a table visual that lists all Customer IDs that do not have a Survey - so, in the above scenario, customers 78 and 91 both do not have surveys yet, but they've been with the company for more than 30 days, so I want to flag these folks.
Then, customer 56 does have a record in the Survey table, but not a record that "counts" in this exercise... so, customer 56 would be flagged as well because he does not have a "Survey 1" OR "Survey 2" OR "Survey 3"... the order doesn't matter, I'm just interested in finding customers who do not have a survey and have been with us for 30 days or more.
Hopefully, that explanation helps -- Appreciate any and all guidance to accomplish this in PBI with conditional columns, maybe merging of tables in PowerQuery or via a DAX measure. I do want to be able to slice this, so a bit of a limitation there maybe.
Thank you!
Here is a solution:
Flag =
VAR _days = INT ( TODAY() - SELECTEDVALUE ( 'Customer Table'[Start Date] ) )
VAR _surveys =
COUNTROWS (
FILTER ( 'Survey Table' ,
CONTAINSSTRING ( [Survey] , "survey" ) )
)
RETURN
IF ( _days > 30 && ISBLANK ( _surveys ) , "Flag" )
Gives the following result in a table visual with the Customer ID column as values:
If you wanted to do it in M / Powerquery
let Source = Excel.CurrentWorkbook(){[Name="CustomerTable"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Customer ID", type text}, {"Start Date", type date}}),
// calculate length of time as a customer, in days
#"Added Custom" = Table.AddColumn(#"Changed Type", "CustomerForDays", each Number.From(Date.From(DateTime.LocalNow())-[Start Date])),
// merge in any customer that also had a survey from SurveyTable query
#"Filtered Rows" = Table.SelectRows(SurveyTable, each Text.Contains([Survey], "Survey")),
#"Merged Queries" = Table.NestedJoin(#"Added Custom",{"Customer ID"},#"Filtered Rows" ,{"Customer ID"},"SurveyTable",JoinKind.LeftOuter),
#"Expanded SurveyTable" = Table.ExpandTableColumn(#"Merged Queries", "SurveyTable", {"Survey"}, {"Survey"}),
// filter out survey<>null and keep Customer>=30 days
#"Filtered Rows1" = Table.SelectRows(#"Expanded SurveyTable", each [Survey] = null and [CustomerForDays] >= 30),
#"Removed Columns" = Table.RemoveColumns(#"Filtered Rows1",{"CustomerForDays", "Survey"})
in #"Removed Columns"
Hope this helps. Considering there is Relationship on CustomerId col (one-to-many from customers to survey),I have created a measure that decides based on 2 conditions u have. In sample i modified the start date for customer 34 to 15th Sept 2021.
Flag =
var days_diff = DATEDIFF(MAX(Customers[Start Date]),NOW(),DAY)
var cust_exists = IF(ISBLANK(MAX(Surveys[customerId])),FALSE(),TRUE())
return IF(AND(cust_exists,days_diff<=30),1,0)