Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Don't miss out! 2025 Microsoft Fabric Community Conference, March 31 - April 2, Las Vegas, Nevada. Use code MSCUST for a $150 discount. Prices go up February 11th. Register now.

Reply
Marsipulami
New Member

Lookup value with condition within a range of dates

Hello Community,

I have been trying for days to implement a lookup function with condition within a range of dates. As a beginner, my knowledge of Power Query is still too limited to solve this task on my own.

In my web searches I have not been able to find any posts that fit my specific case. Several attempts to use chtGPT to solve the problem have also been unsuccessful. .

 

My task:

I have a table tblLookup which contains all previous contribution rates of different insurances over time; these contribution rates are valid from a certain validity date until the time of the introduction of new contribution rates.

In my table tblData I have to assign the contribution rates of the insurances valid at the time of each period.

 

tblLookup:

Health InsuranceValid from DateContribution Rate
ABC Inc01.01.20210,90%
BKK Ltd01.01.20211,50%
XYZ Corp01.01.20211,50%
ABC Inc01.01.20221,20%
BKK Ltd01.01.20221,70%
XYZ Corp01.01.20221,80%
ABC Inc01.01.20231,60%
BKK Ltd01.01.20231,80%
ABC Inc01.01.20241,90%
BKK Ltd01.01.20242,00%

 

tblData:

PeriodEmployeeHealth Insurance
01.12.2021BenABC Inc
01.12.2021DaveBKK Ltd
01.12.2021MikeXYZ Corp
01.02.2022BenABC Inc
01.02.2022DaveBKK Ltd
01.02.2022MikeXYZ Corp
01.08.2023BenABC Inc
01.08.2023DaveBKK Ltd
01.08.2023MikeXYZ Corp
01.02.2024BenABC Inc
01.02.2024DaveBKK Ltd
01.02.2024MikeXYZ Corp

 

Expected Result:

PeriodEmployeeHealth InsuranceContribution Rate
01.12.2021BenABC Inc0,90%
01.12.2021DaveBKK Ltd1,50%
01.12.2021MikeXYZ Corp1,50%
01.02.2022BenABC Inc1,20%
01.02.2022DaveBKK Ltd1,70%
01.02.2022MikeXYZ Corp1,80%
01.08.2023BenABC Inc1,60%
01.08.2023DaveBKK Ltd1,80%
01.08.2023MikeXYZ Corp1,80%
01.02.2024BenABC Inc1,90%
01.02.2024DaveBKK Ltd2,00%
01.02.2024MikeXYZ Corp1,80%

 

My problem:

The query that I created from the code I found works as long as the date in Period falls within a date range (lower/upper limit).

But: as soon as the date in column Period is greater than the maximum date in column Valid from Date , I get null as query result.

Instead, the currently valid contribution rates based on the last valid date should be displayed in these cases. .

 

My Code:

 

 

let
Source = Excel.CurrentWorkbook(){[Name="tblData"]}[Content],

//Buffering this table seems to reduce speed of execution from 60 sec to about 20 sec
#"Buffer tblData" = Table.Buffer(Table.TransformColumnTypes(Source,
{{"Period", type date}, {"Employee", type text}, {"Health Insurance", type text}})),

//Read in table 2 and set data types
//Be sure to change `Name` of table to the actual table name in your workbook
Source2 = Excel.CurrentWorkbook(){[Name="tblLookup"]}[Content],
#"Buffer tblLookup" = Table.Buffer(Table.TransformColumnTypes(Source2,
{{"Health Insurance", type text}, {"Valid from Date", type date}, {"Contribution Rate", Percentage.Type}})),
//Join the two tables based on [Health Insurance]
#"Joined Tables" = Table.NestedJoin(#"Buffer tblData", {"Health Insurance"}, #"Buffer tblLookup", {"Health Insurance"},"Joined"),

//filter Joined subtable
#"Filtered Tables" = Table.AddColumn(#"Joined Tables", "Filtered Table", each
let
dt = [Period],
minDT = List.Min(List.Select([Joined][Valid from Date],each _ >= dt)),
maxDT = List.Max(List.Select([Joined][Valid from Date],each _ <= dt))
in
Table.SelectRows([Joined], each [Valid from Date] <= minDT and [Valid from Date] >= maxDT)),

//Lookup Rate
#"Add Rate" = Table.AddColumn(#"Filtered Tables", "Contribution Rate",
each if Table.IsEmpty([Filtered Table]) then null
else [Filtered Table][#"Contribution Rate"]{0}, Percentage.Type),
#"Removed other Columns" = Table.SelectColumns(#"Add Rate",{"Period", "Employee", "Health Insurance", "Contribution Rate"})
in
#"Removed other Columns"

 

It would be nice if I could receive suggestions for solutions with detailed comments so that I can expand my knowledge of Power Query.

I look forward to your contributions and thank you in advance for your support.

1 ACCEPTED SOLUTION
AlienSx
Super User
Super User

Hello, @Marsipulami if your lookup table is sorted by date (Order. Ascending) then you may try to find the last occurrence of "Valid from" date which is less than or equal to Period providing that insurance company values are equal. List.PositionOf is your friend - use optional occurrence parameter as well as custom equationCriteria. But transform your lookup table into the list first in order to apply List.PositionOf like this:

let
    // get your tables. Sort lookup table by date if nessesary. 
    tblLookup = Excel.CurrentWorkbook(){[Name="tblLookup"]}[Content],
    tblData = Excel.CurrentWorkbook(){[Name="tblData"]}[Content],
    // transform lookup table into a list of row values
    lstLookup = List.Buffer(Table.ToRows(tblLookup)),
    // List.PositionOf finds a position of an item. 
    // Access that item using list_name{item_position}
    // ones the lookup list item is found - grab 2nd element in that list. 
    // To be on a safe side check for errors just in case item is not found
    // with a help of try ... otherwise (which I did not do)
    // read List.PositionOf documentation for more information.
    col = Table.AddColumn(
        tblData, 
        "Contribution Rate",
        (w) => lstLookup{
            List.PositionOf(
                lstLookup, 
                w, Occurrence.Last,
                (x, y) => (y[Health Insurance] = x{0}) and (y[Period] >= x{1})
            )}{2}
    )
in
    col

 

View solution in original post

4 REPLIES 4
dufoq3
Super User
Super User

Hi, different power query solution here:

 

Result

dufoq3_0-1715281443313.png

let
    TableLookup = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcnRyVvDMS1bSUTIw1AMiIwMjQxBHx9JAVSlWJ1rJydtbwackBV2BoY4pVEFEZJSCc35RAW4VWOwwAiswwm0HRIE5HjsgKixw22EMVmCG2w5jQiaYgBXgCQmQAiMdA5CCWAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Health Insurance" = _t, #"Valid from Date" = _t, #"Contribution Rate" = _t]),
    TableLookupChangedType = Table.TransformColumnTypes(TableLookup,{{"Valid from Date", type date}, {"Contribution Rate", Percentage.Type}}),
    TableData = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjDUMzTSMzIwMlTSUXJKzQOSjk7OCp55yUqxOmjSLollqSBV3t4KPiUpmPK+mdkg+YjIKAXn/KICmAIDsAIjXOYjpLGbj5DHZb4FSIExTvPh0jjMh8vjdb8JfvebEHC/CTbzYwE=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Period = _t, Employee = _t, #"Health Insurance" = _t]),
    TableDataChangedType = Table.TransformColumnTypes(TableData,{{"Period", type date}}),
    MergedQueries = Table.NestedJoin(TableDataChangedType, {"Health Insurance"}, TableLookupChangedType, {"Health Insurance"}, "TableLookupChangedType", JoinKind.LeftOuter),
    Ad_ContributionRate = Table.AddColumn(MergedQueries, "Contribution Rate", each List.Last(Table.SelectRows([TableLookupChangedType], (x)=> x[Valid from Date] <= [Period])[Contribution Rate]?), Percentage.Type),
    RemovedColumns = Table.RemoveColumns(Ad_ContributionRate,{"TableLookupChangedType"})
in
    RemovedColumns

Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

AlienSx
Super User
Super User

Hello, @Marsipulami if your lookup table is sorted by date (Order. Ascending) then you may try to find the last occurrence of "Valid from" date which is less than or equal to Period providing that insurance company values are equal. List.PositionOf is your friend - use optional occurrence parameter as well as custom equationCriteria. But transform your lookup table into the list first in order to apply List.PositionOf like this:

let
    // get your tables. Sort lookup table by date if nessesary. 
    tblLookup = Excel.CurrentWorkbook(){[Name="tblLookup"]}[Content],
    tblData = Excel.CurrentWorkbook(){[Name="tblData"]}[Content],
    // transform lookup table into a list of row values
    lstLookup = List.Buffer(Table.ToRows(tblLookup)),
    // List.PositionOf finds a position of an item. 
    // Access that item using list_name{item_position}
    // ones the lookup list item is found - grab 2nd element in that list. 
    // To be on a safe side check for errors just in case item is not found
    // with a help of try ... otherwise (which I did not do)
    // read List.PositionOf documentation for more information.
    col = Table.AddColumn(
        tblData, 
        "Contribution Rate",
        (w) => lstLookup{
            List.PositionOf(
                lstLookup, 
                w, Occurrence.Last,
                (x, y) => (y[Health Insurance] = x{0}) and (y[Period] >= x{1})
            )}{2}
    )
in
    col

 

Anonymous
Not applicable

hi, how would you do this query in DAX as a new column? i have a similar task but i need this in DAX

Hello AlienSx,
great, that's exactly what I was looking for.
Thank you very much for your quick and valuable support.

 

With best regards. 😂

Marsipulami

Helpful resources

Announcements
Las Vegas 2025

Join us at the Microsoft Fabric Community Conference

March 31 - April 2, 2025, in Las Vegas, Nevada. Use code MSCUST for a $150 discount! Prices go up Feb. 11th.

Jan25PBI_Carousel

Power BI Monthly Update - January 2025

Check out the January 2025 Power BI update to learn about new features in Reporting, Modeling, and Data Connectivity.

Jan NL Carousel

Fabric Community Update - January 2025

Find out what's new and trending in the Fabric community.