Power Query - Multiple criteria with dates

fdfordham

New Member
Joined
Aug 12, 2021
Messages
6
Office Version
  1. 365
Platform
  1. Windows
I am having difficulty with merging tables and multiple criteria. I would like to receive "Employee_Rates.True Cost Rate" from matching "Employee_Hours.Employee Name" to "Employee_Rates.Employee Name" and if "Employee_Rates.Start Date" is <= (less than or equal) to "Employee_Hours.Date Worked". I am merging another table into the query and all data is as expected until line #"Merged Queries". After this and #"Expanded Employee_Rates", the data is reduced to one line. The Employee_Hours table has duplicate names with different Start Dates for different True Cost Rates. The following is the code from the editor:

let
Source = Table.NestedJoin(Project_List, {"Project Number"}, Employee_Hours, {"Project Number"}, "Employee_Hours", JoinKind.LeftOuter),
#"Expanded Employee_Hours" = Table.ExpandTableColumn(Source, "Employee_Hours", {"Employee Name", "Date Worked", "Hours Worked "}, {"Employee_Hours.Employee Name", "Employee_Hours.Date Worked", "Employee_Hours.Hours Worked "}),
#"Reordered Columns" = Table.ReorderColumns(#"Expanded Employee_Hours",{"Project Description ", "Project Number", "Employee_Hours.Employee Name", "Employee_Hours.Date Worked", "Employee_Hours.Hours Worked "}),
#"Sorted Rows" = Table.Sort(#"Reordered Columns",{{"Project Description ", Order.Ascending}}),
#"Merged Queries" = Table.NestedJoin(#"Sorted Rows", {"Employee_Hours.Employee Name", "Employee_Hours.Date Worked"}, Employee_Rates, {"Employee Name", "Start Date"}, "Employee_Rates", JoinKind.Inner),
#"Expanded Employee_Rates" = Table.ExpandTableColumn(#"Merged Queries", "Employee_Rates", {"True Cost Rate"}, {"Employee_Rates.True Cost Rate"})
in
#"Expanded Employee_Rates"

I can do this within a spreadsheet, but in Power Query. Hopefully someone can provide some suggestion. And I hope this is enough information.

Thank you!
 

Excel Facts

Difference between two dates
Secret function! Use =DATEDIF(A2,B2,"Y")&" years"&=DATEDIF(A2,B2,"YM")&" months"&=DATEDIF(A2,B2,"MD")&" days"
Hi,

Could you share your table - structure for both (to be joined) tables?
Because from the editor lines I can't find the structure to do "Employee_Rates.Start Date" is <= (less than or equal) to "Employee_Hours.Date Worked"

To show the table structure (if possible) please use XL2BB add-in, this will help us preventing to do a type over from a screenshot.
More info on XL2BB to be found here
 
Upvote 0
I think this is what you are asking for. Thank you for the help.

Employee_Rate Table

Project_True_Cost_Analysis_20210801 - Copy.xlsx
ABCD
3Employee NameStart Date True Cost Rate Billing Rate
7Mary1/1/2000$ 57$ 125
15Steve1/1/2000$ 10$ 10
16Steve5/1/2021$ 212$ 300
Employee Rates




Project_Cost 2 Table

Project_True_Cost_Analysis_20210801 - Copy.xlsx
ABCDE
1Project Description Project NumberEmployee_Hours.Employee NameEmployee_Hours.Date WorkedEmployee_Hours.Hours Worked
219016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/1/20201
319016 - McNair Campus - O'Quinn Tower19-02-004-1Steve4/30/20201
419016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/5/20202
519016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/11/20202
619016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/6/20204
719016 - McNair Campus - O'Quinn Tower19-02-004-1Steve4/29/20204
819016 - McNair Campus - O'Quinn Tower19-02-004-1Steve4/22/20204
919016 - McNair Campus - O'Quinn Tower19-02-004-1Steve4/16/20202
1019016 - McNair Campus - O'Quinn Tower19-02-004-1Steve4/23/20204
1119016 - McNair Campus - O'Quinn Tower19-02-004-1Steve4/28/20202
1219016 - McNair Campus - O'Quinn Tower19-02-004-1Steve4/27/20201
1319016 - McNair Campus - O'Quinn Tower19-02-004-1Steve8/19/20211
1419016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/20/20204
1519016 - McNair Campus - O'Quinn Tower19-02-004-1Steve8/20/20212
1619016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/27/20205
1719016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/26/20203
1819016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/19/20202
1919016 - McNair Campus - O'Quinn Tower19-02-004-1Steve5/13/20204
Project_Cost (2)
 
Upvote 0
Hi,

To do this in Power Query is working with a trick to avoid joining tables only on the exact date. To avoid that you would need to extend the rates table with an end date.
So Reform your Employee RAtes table to this:
Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Start Date", type date}}),
    GroupbyName = Table.Group(#"Changed Type", {"Employee Name"}, {{"MaxDate", each List.Max([Start Date]), type date}}),
    #"Merged Queries" = Table.NestedJoin(#"Changed Type",{"Employee Name"},GroupbyName,{"Employee Name"},"GroupedOnName",JoinKind.LeftOuter), 
    #"Expanded GroupedOnName" = Table.ExpandTableColumn(#"Merged Queries", "GroupedOnName", {"MaxDate"}, {"GroupedOnName.MaxDate"}),
    #"Renamed Columns" = Table.RenameColumns(#"Expanded GroupedOnName",{{"GroupedOnName.MaxDate", "MaxDate"}}),
    #"Added Conditional Column" = Table.AddColumn(#"Renamed Columns", "IsLatest", each if [MaxDate] = [Start Date] then "Yes" else "No"),
    #"Added Conditional Column1" = Table.AddColumn(#"Added Conditional Column", "End Date", each if [IsLatest] = "No" then Date.AddDays([MaxDate],-1)else Date.From(DateTime.LocalNow())),
    #"Changed Type1" = Table.TransformColumnTypes(#"Added Conditional Column1",{{"End Date", type date}}),
    #"Removed Columns" = Table.RemoveColumns(#"Changed Type1",{"MaxDate", "IsLatest"}),
    #"Inserted Date Subtraction" = Table.AddColumn(#"Removed Columns", "Subtraction", each Duration.Days([End Date] - [Start Date]), Int64.Type),
    #"Added Custom" = Table.AddColumn(#"Inserted Date Subtraction", "Merge Date", each List.Dates([Start Date],[Subtraction]+1,#duration(1,0,0,0))),
    #"Expanded Custom" = Table.ExpandListColumn(#"Added Custom", "Merge Date"),
    #"Changed Type2" = Table.TransformColumnTypes(#"Expanded Custom",{{"Merge Date", type date}}),
    #"Removed Columns1" = Table.RemoveColumns(#"Changed Type2",{"Start Date", "End Date", "Subtraction"}),
    #"Reordered Columns" = Table.ReorderColumns(#"Removed Columns1",{"Employee Name", "Merge Date", " True Cost Rate ", "Billing Rate"})
in
    #"Reordered Columns"

This will extend your Rates table to an extended table with all dates within the validity date in rows.
Join the Changed Rates table with the employee hours worked and your done.

As a side note. This technique depends on having an end date. For all open End dates i used todays date, assuming nobody registers hours worked after today because they actually haven't worked them yet.

This is a link to my testfile

There might be other more efficient solutions but this is quickest i could think of.

Hope this helps you.
 
Upvote 0
Addition to previous,

Thought of other more efficient option. A general part of previous applies here as well
Change the query for the Rates Table to this:
Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Start Date", type date}}),
    GroupbyName = Table.Group(#"Changed Type", {"Employee Name"}, {{"MaxDate", each List.Max([Start Date]), type date}}),
    #"Merged Queries" = Table.NestedJoin(#"Changed Type",{"Employee Name"},GroupbyName,{"Employee Name"},"GroupedOnName",JoinKind.LeftOuter), 
    #"Expanded GroupedOnName" = Table.ExpandTableColumn(#"Merged Queries", "GroupedOnName", {"MaxDate"}, {"GroupedOnName.MaxDate"}),
    #"Renamed Columns" = Table.RenameColumns(#"Expanded GroupedOnName",{{"GroupedOnName.MaxDate", "MaxDate"}}),
    #"Added Conditional Column" = Table.AddColumn(#"Renamed Columns", "IsLatest", each if [MaxDate] = [Start Date] then "Yes" else "No"),
    #"Added Conditional Column1" = Table.AddColumn(#"Added Conditional Column", "End Date", each if [IsLatest] = "No" then Date.AddDays([MaxDate],-1)else null),
    #"Changed Type1" = Table.TransformColumnTypes(#"Added Conditional Column1",{{"End Date", type date}}),
    #"Removed Columns" = Table.RemoveColumns(#"Changed Type1",{"MaxDate", "IsLatest"})
in
    #"Removed Columns"

and change the join to this:
Power Query:
let
    Source = Table.NestedJoin(#"Employee Hours", {"Employee_Hours.Employee Name"}, #"Employee Rates (2)", {"Employee Name"}, "Employee Rates", JoinKind.LeftOuter),
    #"Expanded Employee Rates" = Table.ExpandTableColumn(Source, "Employee Rates", {" True Cost Rate ", "Billing Rate", "Employee Name", "End Date", "Start Date"}, {"Employee Rates. True Cost Rate ", "Employee Rates.Billing Rate", "Employee Rates.Employee Name", "Employee Rates.End Date", "Employee Rates.Start Date"}),
    #"Filtered Rows" = Table.SelectRows(#"Expanded Employee Rates", each ([Employee_Hours.Date Worked] >= [Employee Rates.Start Date] and [Employee_Hours.Date Worked] <= [Employee Rates.End Date]) or ([Employee_Hours.Date Worked] >= [Employee Rates.Start Date] and [Employee Rates.End Date] = null)),
    #"Removed Columns" = Table.RemoveColumns(#"Filtered Rows",{"Employee Rates.Employee Name", "Employee Rates.End Date", "Employee Rates.Start Date"})
in
    #"Removed Columns"

Shorter and does the trick:

Testfile with both options here
 
Upvote 0

Forum statistics

Threads
1,223,911
Messages
6,175,323
Members
452,635
Latest member
laura12345

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top