Point-in-time price lookup

hardData modelling~35 min · 7 tests · bitshop

products.price is today’s price. An order from last year was placed at last year’s price. The bitshop price_changes table keeps the history: one row per change, effective from changed_at until the next change for that product.

Write price_at(price_changes, lookups):

  • price_changes has columns product_id, price, changed_at (dates as YYYY-MM-DD strings).
  • lookups has columns product_id, date (also YYYY-MM-DD strings). Rows can repeat and come in any order.
  • For each lookup row, find that product’s most recent change with changed_at <= date. A change dated on the lookup day already applies.
  • If the date is before the product’s first change, or the product has no history, the price is missing (NaN or None).
  • Return a DataFrame with columns product_id, date, price, one row per lookup row, in the same order as lookups. Keep date as the original string.

A plain merge on product_id gives one row per change. You need exactly one per lookup.

>>> price_at(price_changes, pd.DataFrame({"product_id": [1, 1], "date": ["2024-05-10", "2024-05-11"]}))
   product_id        date  price
0           1  2024-05-10  26.42
1           1  2024-05-11  29.63
Learn the ideaRead the lesson →
solution.pyPython 3.14 · Pyodide

Press ⌘ ↵ or Run to check the visible tests. Submit runs the hidden ones too. Everything runs in your browser.

⌘ ↵ to run