Вы ищете представление, из которого вы можете выбрать первый и последний день месяца?
Этот режим создаст представление months
со всеми месяцами с января 1970 года по декабрь 2070 года.
CREATE VIEW months
AS
WITH RECURSIVE cte(i, number_of_year, number_of_month, first_day, last_day)
AS
(
SELECT 1 i,
0 / 12 + 1970 number_of_year,
0 % 12 + 1 number_of_month,
(lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
(lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
UNION ALL
SELECT i + 1 i,
i / 12 + 1970 number_of_year,
i % 12 + 1 number_of_month,
(lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
(lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
FROM cte
WHERE i / 12 + 1970 <= 2070
)
SELECT number_of_year,
number_of_month,
first_day,
last_day
FROM cte;
Но я рекомендую материализовать это для повышения производительности.
CREATE TABLE months
AS
WITH RECURSIVE cte(i, number_of_year, number_of_month, first_day, last_day)
AS
(
SELECT 1 i,
0 / 12 + 1970 number_of_year,
0 % 12 + 1 number_of_month,
(lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
(lpad((0 / 12 + 1970)::text, 4, '0') || '-' || lpad((0 % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
UNION ALL
SELECT i + 1 i,
i / 12 + 1970 number_of_year,
i % 12 + 1 number_of_month,
(lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp first_day,
(lpad((i / 12 + 1970)::text, 4, '0') || '-' || lpad((i % 12 + 1)::text, 2, '0') || '-01')::timestamp + INTERVAL '1 month - 1 day' last_day
FROM cte
WHERE i / 12 + 1970 <= 2070
)
SELECT number_of_year,
number_of_month,
first_day,
last_day
FROM cte;
Я полагаю, вы будете запрашивать это так:
SELECT first_day,
last_day
FROM months
WHERE number_of_year = <year>
AND number_of_month = <month>;
Затем также создайте следующий индексподдержать его.
CREATE INDEX months_number_of_year_number_of_month_first_day_last_day
ON months (number_of_year,
number_of_month,
first_day,
last_day);