Latest change on or before the snapshot date
WITH latest_changes AS (
SELECT
product_id,
MAX(change_date) AS last_change_date
FROM products
WHERE change_date <= '2019-08-16'
GROUP BY product_id
)
SELECT
p.product_id,
COALESCE(pr.new_price, 10) AS price
FROM (SELECT DISTINCT product_id FROM products) p
LEFT JOIN latest_changes lc
ON p.product_id = lc.product_id
LEFT JOIN products pr
ON pr.product_id = lc.product_id
AND pr.change_date = lc.last_change_dateThis is the most robust point-in-time pattern. First isolate the last valid change before the cutoff date, then join back to the source rows and fall back to the default price when no earlier change exists.