How to merge tables based on largest date smaller than date

th081

Board Regular
Joined
Mar 26, 2006
Messages
98
Office Version
  1. 365
Platform
  1. Windows
Hi,

I have to tables one with a name, date and some other records. The second table has name, date and some other records, however in the second table there will be several records with the same name.

I want all the records in table one matching name and date in table 2, but the date in table 2 will not be a exact match. I want the date in table 2 to match to the largest date less than the date in table 1.

Table 1

James, 01/02/23, RecA, RecB, RecC

Table 2

James, 15/12/22, RecD, RecE
James, 12/01/23, RecF, Reg G
James, 29/01/23, RecH, RecI
James, 03/02/23, RecJ, RecK

The merge will bring back the third row in table 2 as that is the highest date less or same as the date in table 1

Can anyone help
 

Excel Facts

How can you automate Excel?
Press Alt+F11 from Windows Excel to open the Visual Basic for Applications (VBA) editor.
I would do something like the following.
1- Merge two tables on the Name field and get all matching Table2 rows
2- Select the rows less than or equal to the corresponding Table1 Date field value
3- Group on Date field and get the row with the max Date value
4- There are only the Name and Date fields left. Merge this table with the original Table2 on these two fields
5- Expand the missing columns from the nested table

Open the PQ editor, create a new blank query, click on Advanced Editor, copy and paste the following code, and click Done. Make sure to adapt the table names in the code below - [Name="Table1"] and [Name="Table2"] might need to be changed according to your table names.
Power Query:
let
    // Source for Table1
    Table1 = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    // Source for Table2
    Table2 = Excel.CurrentWorkbook(){[Name="Table2"]}[Content],
    // Merge two tables
    Merge = Table.NestedJoin(Table2, {"Name"}, Table1, {"Name"}, "Table1", JoinKind.LeftOuter),
    // Filter Table2 according to Date
    FilterRows = Table.SelectRows(Merge, each [Date] <= [Table1]{0}[Date]),
    // Find the earliest date rows by grouping the table
    Highest = Table.Group(FilterRows, {"Name"}, {{"Date", each List.Max([Date]), type datetime}}),
    // Merge on Table2 to get the missing columns after grouping 
    MergeAgain = Table.NestedJoin(Highest, {"Name", "Date"}, Table2, {"Name", "Date"}, "Table2"),
    // Expand the missing columns
    Result = Table.ExpandTableColumn(MergeAgain, "Table2", List.RemoveFirstN(Table.ColumnNames(Table2), 2) )
in
    Result
 
Upvote 0
Thank you smozgur,

your code seems to only to only bring back 1 record from table 2.

My Table 1 is as below:

NameDateMisc1Misc2
James
01/02/2023​
1​
4​
Bond
02/02/2023​
2​
5​
James
03/02/2023​
3​
7​
James
04/02/2023​
4​
8​
James
04/10/2023​
4.1​
8.2​

Table 2 as below:


NameDateMisc3Misc4
James
15/12/2022​
9​
13​
James
12/01/2023​
10​
14​
James
29/01/2023​
11​
15​
James
04/02/2023​
12​
16​

copying your code i was expecting the bwlow:

James
01/02/2023​
1​
4​
James
29/01/2023​
11​
15​
the record in table 2 dated 29/01/23 is the higest date less than or equal to 01/02/23 for James
Bond
02/02/2023​
2​
5​
nullnullnullnullno match
James
03/02/2023​
3​
7​
James
29/01/2023​
11​
15​
the record in table 2 dated 29/01/23 is the higest date less than or equal to 03/02/23 for James
James
04/02/2023​
4​
8​
James
04/02/2023​
12​
16​
04/02/23 is a exact match
James
04/10/2023​
4.1​
8.2​
James
04/02/2023​
12​
16​
the record in table 2 dated 04/02/23 is the higest date less than or equal to 04/10/23 for James


however the code only returns:

NameDateMisc3Misc4
James
29/01/2023 00:00​
11​
15​
 
Upvote 0
From the first sample data, I thought Table1 to Table2 was a one-to-many relationship, but it was apparently many-to-many.

Here is the modified code for the new sample data and the expected result.
Note: Your initial description says "I want all the records in table one matching name and date in table 2", however, the desired result contains Bond while it is not matching the data in Table2. If the initial description is correct, then remove or [Date] is null from the code.

Power Query:
let
    Table1 = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    Table2 = Excel.CurrentWorkbook(){[Name="Table2"]}[Content],
    Merge = Table.NestedJoin(Table1, {"Name"}, Table2, {"Name"}, "Table2", JoinKind.FullOuter),

    Highest = Table.AddColumn(Merge, "Highest",
            (r) =>
                let
                    Result = Table.SelectRows(r[Table2], each [Date] <= r[Date] or [Date] is null)
                in
                    Table.First(Table.Sort(Result, {"Date", Order.Descending}))
            ),
    Expand = Table.ExpandRecordColumn(Highest, "Highest", {"Name", "Date", "Misc3", "Misc4"}, {"H.Name", "H.Date", "Misc3", "Misc4"}),
    Result = Table.RemoveColumns(Expand,{"Table2"})
in
    Result

Source data and result below (the data format is m/d/y in my data but it will work correctly with your d/m/y format in your computer)
Table1:
NameDateMisc1Misc2
James2/1/202314
Bond2/2/202325
James2/3/202337
James2/4/202348
James10/4/20234.18.2

Table2:
NameDateMisc3Misc4
James12/15/2022913
James1/12/20231014
James1/29/20231115
James2/4/20231216

Result:
NameDateMisc1Misc2H.NameH.DateMisc3Misc4
James2/1/202314James1/29/20231115
James2/3/202337James1/29/20231115
James2/4/202348James2/4/20231216
James10/4/20234.18.2James2/4/20231216
Bond2/2/202325
 
Last edited:
Upvote 1
Solution
The following
Power Query:
Table.First(Table.Sort(Result, {"Date", Order.Descending}))
could be changed by using a single function - Table.Max() (and most proper one for the case actually, no need to sort and get the top row. Apparently, I didn't know that we have a Table.Max function. Good learning.)
Power Query:
Table.Max(Result, "Date")
 
Upvote 0

Forum statistics

Threads
1,223,319
Messages
6,171,427
Members
452,402
Latest member
siduslevis

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