SELECT
m.amount
FROM
measurement m,
to_date('Dec 01 1900', 'Mon DD YYYY') AS A(d1),
to_date('Feb 28 1900', 'Mon DD YYYY') AS B(d2),
to_date('Feb 28 1901', 'Mon DD YYYY') AS C(d3)
WHERE m.taken
BETWEEN
d1 AND
CASE WHEN d2 < d1 THEN d3 ELSE d2 END
Ссылки: условные выражения , функции форматирования типа данных .
РЕДАКТИРОВАТЬ: Извините, я думал, что вы хотели конкретный год:
SELECT
amount
FROM
(SELECT
M.amount, M.taken,
to_date('Dec 01 ' || extract(YEAR FROM M.taken), 'Mon DD YYYY'),
to_date('Feb 28 ' || extract(YEAR FROM M.taken), 'Mon DD YYYY')
FROM
measurement AS M
) AS A(amount, taken, d1, d2)
WHERE
(d2 >= d1 AND taken BETWEEN d1 AND d2)
OR
(d2 < d1 AND (taken <= d2 OR taken >= d1));
Если набор большой, у него мало шансов для оптимизации. В этом случае у вас может быть функция SQL, которая преобразует все даты в определенный год (say taken - (extract(year from taken) - 1900) * '1 year'::interval)
и затем сравнивает их с 02 декабря 1900 года и 28 февраля 1900 года. Таким образом, вы можете индексировать результат этой функции преобразования даты нужно вычислить две даты для каждой записи.