Если у вас была возможность изменить структуру таблицы, другой подход заключался бы в том, чтобы в вашей таблице были как start_date, так и end_date, таким образом ваши записи не будут зависеть от предыдущей / следующей строки, и ваш запрос будет легче писать. См. Медленно меняя размер - Тип 2
Если вы хотите решить проблему с существующей структурой, в PostgresSQL вы можете использовать LIMIT 1
для получения последней записи перед изменением_даты:
SELECT
*
FROM
price_history
WHERE
product_id in (1,2)
AND changed_date >= '2018-01-01'
UNION ALL
-- this would give you the latest price before changed_date
SELECT
*
FROM
price_history
WHERE
product_id in (1,2)
AND changed_date < '2018-01-01'
ORDER BY
changed_date DESC
LIMIT 1